对两个 Pandas DataFrame 进行逐行比较以提取匹配结果
Row-wise comparison of two Pandas DataFrames to extract matched results
我有一个名为 df_ref
的 pandas DataFrame,它类似于:
a b c result
0 (-0.001, 0.00482] (-0.001, 1.0] (-0.001, 1.0] 0.622745
1 (-0.001, 0.00482] (-0.001, 1.0] (-0.001, 1.0] 0.450869
2 (-0.001, 0.00482] (-0.001, 1.0] (1.0, 5.0] 0.693840
3 (-0.001, 0.00482] (-0.001, 1.0] (1.0, 5.0] 0.484881
4 (-0.001, 0.00482] (-0.001, 1.0] (5.0, 13.0] 0.687814
... ... ... ... ... ... ...
91 (17.953, 90.0] (4.0, 480.0] (1.0, 5.0] 0.500905
92 (17.953, 90.0] (4.0, 480.0] (5.0, 13.0] 0.500905
93 (17.953, 90.0] (4.0, 480.0] (5.0, 13.0] 0.500905
94 (17.953, 90.0] (4.0, 480.0] (13.0, 1103.0] 0.500905
95 (17.953, 90.0] (4.0, 480.0] (13.0, 1103.0] 0.500905
和另一个名为 df
的 DataFrame,类似于:
a b c
1 0.004213 11.0 11.0
2 32.326794 0.0 0.0
3 5.415845 1.0 1.0
4 0.001968 10.0 41.0
5 0.014745 9.0 13.0
... ... ... ... ... ...
1435435 0.000185 1.0 1.0
1435436 89.999919 0.0 0.0
1435437 4.788090 1.0 1.0
1435438 7.441620 0.0 22.0
1435439 0.001053 1.0 1.0
我要将df
的每一行与df_ref
的所有行进行比较,判断它们属于哪一行,并从[=13=中提取对应的result
值] 并将这些值放入包含 1,435,439 个元素的列表中(或者只是 df
中的一个新列,两者都有效)。由于数据很大,因此需要有效编码,所以我明白简单的循环可能不是最好的方法,这就是我寻求帮助的原因。
我假设 df_ref
的 a
、b
和 c
列中值的类型是 intervalIndex 并且将它们组合起来总能得到一个独特的组合。如果是这种情况,那么我想解决方案可能只是为两个 dfs 设置索引并将它们组合为 pe
In [1]: import pandas as pd
...:
...: df_ref = pd.DataFrame({
...: "a": pd.IntervalIndex.from_tuples([(-0.001, 0.00482), (-0.001, 0.00482), (-0.001, 0.00482), (-0.001, 0.00482), (1, 2)]),
...: "b": pd.IntervalIndex.from_tuples([(-0.001, 1.0), (-0.001, 1.0), (-0.001, 1.0), (1., 2.), (2, 3)]),
...: "c": pd.IntervalIndex.from_tuples([(-0.001, 1.0), (1.0, 2.0), (2.0, 5.0), (5.1, 10.0), (1, 2)]),
...: 'result': [0.622745, 0.450869, 0.693840, 0.484881, 10]
...: })
...:
...: df = pd.DataFrame([{'a': 0.003, 'b': 0.004, 'c': 0.4}, {'a': 2., 'b': 3, 'c': 0.1}])
In [2]: df_ref_idx = df_ref.set_index(['a', 'b', 'c'])
In [3]: df_idx = df.set_index(['a', 'b', 'c'])
In [4]: df_idx['result'] = df_ref_idx['result']
In [5]: df_idx
Out[5]:
result
a b c
0.003 0.004 0.4 0.622745
2.000 3.000 0.1 NaN
创建虚拟数据框花了我一些时间,以后您可能想分享一个片段以轻松重新创建它们(根据我的回答),以便其他人更容易帮助您。
如果这没有帮助,请告诉我
我会做类似下面的事情。制作一个名为 df_ref2
的 df_ref
副本,将元组拆分为单独的列 a_low
、a_high
等。然后像这样连接帧
df = df.join(df_ref2,
on=( (df.a >= df_ref2.a_low) & (df.a <= df_ref2.a_high) &
(df.b >= df_ref2.b_low) & (df.b <= df_ref2.b_high) &
(df.c >= df_ref2.c_low) & (df.c <= df_ref2.c_high) ),
how='inner')
df = df.drop('a_low', 'a_high', 'b_low', 'b_high', 'c_low', 'c_high')
现在您已将 result
列连接到 df
。请注意,您可能会增加行数,因为每个 df 行都可以匹配多个 df_ref 行,正如您看到的 df_ref 的前两行具有相同的间隔。
我有一个名为 df_ref
的 pandas DataFrame,它类似于:
a b c result
0 (-0.001, 0.00482] (-0.001, 1.0] (-0.001, 1.0] 0.622745
1 (-0.001, 0.00482] (-0.001, 1.0] (-0.001, 1.0] 0.450869
2 (-0.001, 0.00482] (-0.001, 1.0] (1.0, 5.0] 0.693840
3 (-0.001, 0.00482] (-0.001, 1.0] (1.0, 5.0] 0.484881
4 (-0.001, 0.00482] (-0.001, 1.0] (5.0, 13.0] 0.687814
... ... ... ... ... ... ...
91 (17.953, 90.0] (4.0, 480.0] (1.0, 5.0] 0.500905
92 (17.953, 90.0] (4.0, 480.0] (5.0, 13.0] 0.500905
93 (17.953, 90.0] (4.0, 480.0] (5.0, 13.0] 0.500905
94 (17.953, 90.0] (4.0, 480.0] (13.0, 1103.0] 0.500905
95 (17.953, 90.0] (4.0, 480.0] (13.0, 1103.0] 0.500905
和另一个名为 df
的 DataFrame,类似于:
a b c
1 0.004213 11.0 11.0
2 32.326794 0.0 0.0
3 5.415845 1.0 1.0
4 0.001968 10.0 41.0
5 0.014745 9.0 13.0
... ... ... ... ... ...
1435435 0.000185 1.0 1.0
1435436 89.999919 0.0 0.0
1435437 4.788090 1.0 1.0
1435438 7.441620 0.0 22.0
1435439 0.001053 1.0 1.0
我要将df
的每一行与df_ref
的所有行进行比较,判断它们属于哪一行,并从[=13=中提取对应的result
值] 并将这些值放入包含 1,435,439 个元素的列表中(或者只是 df
中的一个新列,两者都有效)。由于数据很大,因此需要有效编码,所以我明白简单的循环可能不是最好的方法,这就是我寻求帮助的原因。
我假设 df_ref
的 a
、b
和 c
列中值的类型是 intervalIndex 并且将它们组合起来总能得到一个独特的组合。如果是这种情况,那么我想解决方案可能只是为两个 dfs 设置索引并将它们组合为 pe
In [1]: import pandas as pd
...:
...: df_ref = pd.DataFrame({
...: "a": pd.IntervalIndex.from_tuples([(-0.001, 0.00482), (-0.001, 0.00482), (-0.001, 0.00482), (-0.001, 0.00482), (1, 2)]),
...: "b": pd.IntervalIndex.from_tuples([(-0.001, 1.0), (-0.001, 1.0), (-0.001, 1.0), (1., 2.), (2, 3)]),
...: "c": pd.IntervalIndex.from_tuples([(-0.001, 1.0), (1.0, 2.0), (2.0, 5.0), (5.1, 10.0), (1, 2)]),
...: 'result': [0.622745, 0.450869, 0.693840, 0.484881, 10]
...: })
...:
...: df = pd.DataFrame([{'a': 0.003, 'b': 0.004, 'c': 0.4}, {'a': 2., 'b': 3, 'c': 0.1}])
In [2]: df_ref_idx = df_ref.set_index(['a', 'b', 'c'])
In [3]: df_idx = df.set_index(['a', 'b', 'c'])
In [4]: df_idx['result'] = df_ref_idx['result']
In [5]: df_idx
Out[5]:
result
a b c
0.003 0.004 0.4 0.622745
2.000 3.000 0.1 NaN
创建虚拟数据框花了我一些时间,以后您可能想分享一个片段以轻松重新创建它们(根据我的回答),以便其他人更容易帮助您。
如果这没有帮助,请告诉我
我会做类似下面的事情。制作一个名为 df_ref2
的 df_ref
副本,将元组拆分为单独的列 a_low
、a_high
等。然后像这样连接帧
df = df.join(df_ref2,
on=( (df.a >= df_ref2.a_low) & (df.a <= df_ref2.a_high) &
(df.b >= df_ref2.b_low) & (df.b <= df_ref2.b_high) &
(df.c >= df_ref2.c_low) & (df.c <= df_ref2.c_high) ),
how='inner')
df = df.drop('a_low', 'a_high', 'b_low', 'b_high', 'c_low', 'c_high')
现在您已将 result
列连接到 df
。请注意,您可能会增加行数,因为每个 df 行都可以匹配多个 df_ref 行,正如您看到的 df_ref 的前两行具有相同的间隔。