我能使用pandas.dataframe.isin()函数并带有数值容差参数吗?

8

在这种情况下,您可以创建 A 和 B 的副本,将其四舍五入到最近的整数,然后使用它们来识别原始列中的有效索引值。换句话说,您可以在数据侧实现公差,而不是在函数侧实现。 - Sohier Dane
1个回答

15

你可以使用numpy的isclose函数进行类似的操作:

df[np.isclose(df['A'].values[:, None], [3, 6], atol=.5).any(axis=1)]
Out: 
     A    B
1  6.0  2.0
2  3.3  3.2

np.isclose 返回以下内容:

np.isclose(df['A'].values[:, None], [3, 6], atol=.5)
Out: 
array([[False, False],
       [False,  True],
       [ True, False],
       [False, False]], dtype=bool)
这是对 df['A'] 的元素和 [3, 6] 进行成对比较的(这就是为什么我们需要 df['A'].values[: None] - 用于广播)。由于您要查找它是否接近列表中的任何一个值,因此我们在结尾处调用 .any(axis=1)
对于多列数据,只需稍微调整一下切片:
mask = np.isclose(df[['A', 'B']].values[:, :, None], [3, 6], atol=0.5).any(axis=(1, 2))
mask
Out: array([False,  True,  True, False], dtype=bool)

你可以使用这个掩码来切片DataFrame(即 df[mask])。


如果你想将df['A']df['B'](以及可能的其他列)与不同的向量进行比较,你可以创建两个不同的掩码:

mask1 = np.isclose(df['A'].values[:, None], [1, 2, 3], atol=.5).any(axis=1)
mask2 = np.isclose(df['B'].values[:, None], [4, 5], atol=.5).any(axis=1)
mask3 = ...

然后切片:

df[mask1 & mask2]  # or df[mask1 & mask2 & mask3 & ...]

@webmaker 当我尝试时,它返回一个空的DataFrame,因为D列中的值小于0.15(您传递了0.1作为公差,列表中最小的值为0.25,因此它不会对任何值返回True。这样合适吗?) - ayhan
1
这件事情有点复杂,但我设法解决了问题。现在我正在尝试找出如何一次处理多个列。也许是通过连接/合并df2和df3来实现?df2=df[np.isclose(df['B'].values[:, None], [0.939,0.874,1.0, ], atol=.05).any(axis=1)] df3=df[np.isclose(df['A'].values[:, None], [-0.12,0.0,0.12], atol=.05).any(axis=1)] - webmaker
1
@webmaker 我已经编辑了帖子,包括多列的解决方案。 - ayhan
抱歉,我可能误解了。您有不同的向量要比较列A和B吗?如果是这样,我认为您需要将它们保存为两个掩码(一个用于A,一个用于B),然后使用 df [mask1&mask2] - ayhan
类似这样的编程内容:mask = np.isclose(df[['A', 'B', 'C', 'D']].values[:, :, :,:,None], [a_val, b_val, c_val, d_val], atol=0.5).any(axis=(1, 2,3,4)),其中a_val对应于df ['A'],b_val对应于df ['B']等。 - webmaker
@webmaker 在这种情况下,您需要创建多个掩码。切片[:, :, None]从2D到3D,因此列数在这里不相关。如果您有4个,仍将使用[:, :, None]。答案中关于多列的部分也适用于df[['A', 'B', 'C', 'D']],只要您将其与单个列表/数组进行比较即可。我已添加了有关创建不同掩码的部分。 - ayhan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接