Python np.allclose抛出一个TypeError:当dataframe在一行中有字符串时,此类型未实现

Python np.allclose抛出一个TypeError:当dataframe在一行中有字符串时,此类型未实现,python,pandas,dataframe,Python,Pandas,Dataframe,我试图在给定公差范围内比较数据框内的值是否相等。np.allclose是一个完美的候选者,但是当我的数据帧有字符串值时,它会抛出一个TypeError:没有为这种类型实现。我无法知道他们的字符串是否在一行中 范例 old = pd.DataFrame({'a': [1, np.nan, 3], 'b': [4,"OK", 6]}, index=['x', 'y', 'z']) new = pd.DataFrame(

我试图在给定公差范围内比较数据框内的值是否相等。np.allclose是一个完美的候选者,但是当我的数据帧有字符串值时,它会抛出一个TypeError:没有为这种类型实现。我无法知道他们的字符串是否在一行中

范例

old = pd.DataFrame({'a': [1, np.nan, 3],
                    'b': [4,"OK", 6]},
                    index=['x', 'y', 'z'])

new = pd.DataFrame({'a': [1, np.nan, 3],
                    'b': [4, "OK", 6]},
                    index=['x', 'y', 'z'])

示例中的列“b”包含混合类型;字符串和整数。 不能将字符串与allclose进行比较,因为字符串可能不同,也可能不同。 如果可能的话,您应该对数据进行组织,以便列为单一类型。如果有,可以使用np.allclose比较数字列,使用标准的
=
操作符比较包含字符串的列。 在本例中,“a”列为数字列,因此np.allclose适用于:

In [25]: np.allclose(old.a, new.a)
Out[25]: False
但是,它返回了
False
,因为等于null值总是返回
False
,这是比较数据帧时需要注意的另一个细微之处。在这种情况下,你可以这样做

In [25]: np.allclose(old.fillna(value=0).a, new.fillna(value=0).a)
Out[25]: True
在您给出的小示例中,数据帧的转置具有单一类型的列,因此您可能应该使用该类型。但是,请注意,仅仅进行转置不会改变数据类型

In [18]: old.T.dtypes

Out[18]:
x    object
y    object
z    object
但是使用convert_objects方法将

In [20]: old.T.convert_objects().dtypes
Out[20]:
x    float64
y     object
z    float64
dtype: object
通常,您可以通过调用DataFrame.dtypes来检查每列的数据类型。您可以使用以下命令选择字符串(对象)列

obj_cols = df.columns[df.dtypes == object]
num_cols = df.columns[df.dtypes != object]   #this would also include any time columns
那就做吧

np.allclose(df1[num_cols].fillna(0), df2[num_cols].fillna(0))

编辑: 在更一般的设置中,您可能希望在处理NAN时更加小心。您可以执行上述操作,但也要确保空条目完全匹配,因为用0替换nan可能会产生不需要的相等(一个数据帧中可能有0,另一个数据帧中可能有nan,并且仍然会获得相等,对于字符串也是如此)。您可以按如下方式执行此操作:

(old.isnull() == new.isnull()).all().all()

您可以单独或使用
info()
检查列上的数据类型。浮点数和整数不能有字符串,对象当然可以。是一个列既可以有数字值也可以有字符串值,而您无法事先知道该列中的特定行是否有字符串或数字值,还是一行可以包含所有字符串值或所有数字值?在后一种情况下,听起来行应该是列,反之亦然。请提供一个示例数据框。@JoeCondron这是一个数据框既可以有数字值也可以有字符串值的情况。我想你误解了我的意思。数据帧是否具有不同的类型并不重要,重要的是单个列是否具有混合类型。当列为单一类型时,数据帧工作得最好。通常,列表示字段,行表示记录。例如,数据框可以包含一组人的姓名和年龄。在这种情况下,通常会对其进行组织,以便有一个age列(int或float类型)和一个Name列object类型。然后每一行代表一个人。你明白我的意思吗?不客气。有关更健壮的空值处理,请参见编辑。
(old.isnull() == new.isnull()).all().all()