我有两个熊猫数据框:
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.3221
的 df1
,我想检查 df2['col1']
中是否存在此值,错误为 0.005
(在此示例中 5.326
来自 {{1 }} 应该被视为等于 df2['col1']
) 并制作第三个数据框来保存来自 5.3221
和 df1
的两列,其中上述条件为真。
预期输出为:
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
也用于查找单词匹配而不是整数。我的情况完全不同。
答案 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)