如何根据错误值找到两个熊猫系列之间的交集

时间:2021-07-28 11:31:57

标签: python pandas dataframe numpy

我有两个熊猫数据框:

df1 = pd.DataFrame({'col1': [1.2574, 5.3221, 4.3215, 9.8841], 'col2': ['a', 'b', 'c', 'd']})
df2 = pd.DataFrame({'col1': [4.326, 9.89, 5.326, 1.2654], 'col2': ['w', 'x', 'y', 'z']})

现在我想比较两个数据帧的 col1 中的值。考虑来自 5.3221df1,我想检查 df2['col1'] 中是否存在此值,错误为 0.005(在此示例中 5.326 来自 {{1 }} 应该被视为等于 df2['col1']) 并制作第三个数据框来保存来自 5.3221df1 的两列,其中上述条件为真。

预期输出为:

df2

我定义了一个能够处理错误情况的函数:

    col1    col2    col1.1  col2.2
0   5.3221  b       5.236   y
1   4.3215  c       4.326   w

但我不知道如何在不使用 def close(a, b, e=0.005): return round(abs(a - b), 3) <= e 循环的情况下将其应用于数据。我也知道我可以使用 for,但我不知道如何使用。

任何帮助将不胜感激:)

编辑:建议的重复答案不能解决我的问题。该问题仅适用于基于相似的索引组合两个数据帧。 numpy.intersect1d 也用于查找单词匹配而不是整数。我的情况完全不同。

2 个答案:

答案 0 :(得分:1)

NumPy 的广播可用于交叉比较并获取每个帧中差异落入误差范围的索引。然后我们对帧进行索引并连接结果:

# find where two frames are close
eps = 0.005
diff = np.abs(df1.col1.to_numpy()[:, np.newaxis] - df2.col1.to_numpy())
inds_1, inds_2 = np.where(diff <= eps)

# filter the frames with these indices
first = df1.iloc[inds_1].reset_index(drop=True)
second = df2.iloc[inds_2].reset_index(drop=True)

# adjust column names of the second one, e.g., "col2.2"
second.columns = [col + f".{j}" for j, col in enumerate(second.columns, start=1)]

# put together
result = pd.concat([first, second], axis=1)

得到

>>> result

     col1 col2  col1.1 col2.2
0  5.3221    b   5.326      y
1  4.3215    c   4.326      w

中间结果 diff 是:

>>> diff

array([[3.0686e+00, 8.6326e+00, 4.0686e+00, 8.0000e-03],
       [9.9610e-01, 4.5679e+00, 3.9000e-03, 4.0567e+00],
       [4.5000e-03, 5.5685e+00, 1.0045e+00, 3.0561e+00],
       [5.5581e+00, 5.9000e-03, 4.5581e+00, 8.6187e+00]])

形状为 (len(df1), len(df2)),其中第 ij 个条目是 df1.col1[i] - df2.col1[j]

答案 1 :(得分:1)

我添加了哪些词的代码

首先计算每个点之间的距离作为交叉,然后过滤。 获取这些行并合并

import pandas as pd
import numpy as np

df1 = pd.DataFrame({'col1': [1.2574, 5.3221, 4.3215, 9.8841], 'col2': ['a', 'b', 'c', 'd']})
df2 = pd.DataFrame({'col1': [4.326, 9.89, 5.326, 1.2654], 'col2': ['w', 'x', 'y', 'z']})

# Get the target columns
c11 = df1['col1'].to_numpy()
c21 = df2['col1'].to_numpy()

# calculate cross errors by broadcast and filter columns
# these will be indices of rows to be inserted in new df
c = np.argwhere(np.abs(c11[:, np.newaxis] - c21) < 0.005)


x = pd.DataFrame()
# Insert by removing index otherwise it will try to match the indexs are change row orders
x[['col1', 'col2']] = df1.iloc[c[:, 0]][['col1', 'col2']].reset_index(drop=True)
x[['col1.1', 'col2.2']] = df2.iloc[c[:, 1]][['col1', 'col2']].reset_index(drop=True)

print(x)