检查 Pandas DataFrame 列是否包含浮点精度内的重复项

Check whether Pandas DataFrame column contains duplicates within floating point precision

我有一个数据框,df,包含 4 列的 xyz 点,xyzClassification,全部包含浮动。数据框是通过连接另外两个数据框 df1df2.

创建的

df2 中的所有点都是 df1 中的点的子集,但是这两个数据帧在不同的软件中进行了不同的处理。 df2 中的所有点都具有 14 的 class 化。df1 中的点中的 None 是 class 14。因此在 df 中有点本质上 xyz 重复项(这些 xyz 重复项的数量是 len(df2))其中一半是 class 14. 我想找到这些重复项并丢弃那些不是 class 14.

我说这些行基本上 xyz 重复,因为在之前的处理过程中,许多行都引入了浮点错误。

>>> # make example data,
>>> # small differences introduced on 2nd data
>>> x1 = np.array([0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0])
>>> x2 = x1[:4] + np.array([0, 0, 3e-13, 0])

>>> y1 = np.array([10.0, 11.01, 12.0, 13.0, 14.0, 15.0, 16.0])
>>> y2 = y1[:4] + np.array([0, 0, 3e-13, 4e-13])

>>> z1 = np.array([10.0, 10.1, 10.2, 10.3, 10.4, 10.5, 10.6])
>>> z2 = z1[:4] + np.array([0.0, 0.0, 3e-13, 4e-13])

>>> df1 = pd.DataFrame(columns=['x', 'y', 'z', 'Classification'])
>>> df1['x'] = x1
>>> df1['y'] = y1
>>> df1['z'] = z1
>>> df1['Classifcation'] = 0

>>> df2 = pd.DataFrame(columns=['x', 'y', 'z', 'Classification'])
>>> df2['x'] = x2
>>> df2['y'] = y2
>>> df2['z'] = z2
>>> df2['Classifcation'] = 14

>>> df1
     x      y     z  Classification
0  0.0  10.00  10.0               0
1  1.0  11.01  10.1               0
2  2.0  12.00  10.2               0
3  3.0  13.00  10.3               0
4  4.0  14.00  10.4               0
5  5.0  15.00  10.5               0
6  6.0  16.00  10.6               0

>>> df2
     x    y             z  Classification
0  0.0  0.0  3.000000e-13              14
1  1.0  1.0  1.000000e+00              14
2  2.0  2.0  2.000000e+00              14
3  3.0  3.0  3.000000e+00              14

>>> df = pd.concat ([df1, df2], axis=0)
>>> df
     x      y             z  Classification
0  0.0  10.00  1.000000e+01               0
1  1.0  11.01  1.010000e+01               0
2  2.0  12.00  1.020000e+01               0
3  3.0  13.00  1.030000e+01               0
4  4.0  14.00  1.040000e+01               0
5  5.0  15.00  1.050000e+01               0
6  6.0  16.00  1.060000e+01               0
0  0.0   0.00  3.000000e-13              14
1  1.0   1.00  1.000000e+00              14
2  2.0   2.00  2.000000e+00              14
3  3.0   3.00  3.000000e+00              14

本来我试过

>>> df0 = df.loc[~((df.duplicated(subset=['x', 'y', 'z'],
                          keep=False))
                 & (df.Classification != 14))]

>>> df0
     x      y     z  Classification
2  2.0  12.00  10.2               0
3  3.0  13.00  10.3               0
4  4.0  14.00  10.4               0
5  5.0  15.00  10.5               0
6  6.0  16.00  10.6               0
0  0.0  10.00  10.0              14
1  1.0  11.01  10.1              14
2  2.0  12.00  10.2              14
3  3.0  13.00  10.3              14

>>> len(df), len(df0)
(11, 9)

这丢弃了所有非 14-classifed exact 重复项,但错过了由浮点数错误。

我需要做一些类似 df.duplicated 的事情,但具有 numpy.isclose 的行为,以便在一定公差范围内的值将被视为重复项。

谢谢

一种方法是删除 concat 之前的重复项,据我所知,您正在尝试删除 df1 中已经存在于 df2 中的行。这里的技巧是使用 isin 并创建一个可以轻松比较两个数据帧的键,您可以使用字符串格式并设置小数点(下面的示例使用 5 点)。

df_1['key'] = df_1.apply(lambda row: f'{row["X"]:.5f}-{row["Y"]:.5f}-{row["Z"]:.5f}', axis=1)
df_2['key'] = df_2.apply(lambda row: f'{row["X"]:.5f}-{row["Y"]:.5f}-{row["Z"]:.5f}', axis=1)
df_1 = df_1[df_1['key'].isin(df_2['key'])==False]
combined = pd.concat([df_1, df_2])