对两个 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_refabc 列中值的类型是 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_ref2df_ref 副本,将元组拆分为单独的列 a_lowa_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 的前两行具有相同的间隔。