繁体   English   中英

如何连接两个数据帧,其 2 列值在某个 2 个范围 python 内?

[英]How to join two dataframes for which 2 columns values are within a certain 2 ranges python?

我有 2 个数据框

print(df1)
            Name df1  RT [min]  Molecular Weight  RT [min]+0.2  RT [min]-0.2     Molecular Weight + 0.2  Molecular Weight - 0.2  
0  unknow compound 1     7.590         194.04212         7.790         7.390                  194.24212               193.84212  
1  unknow compound 2     7.510         194.15000         7.710         7.310                  194.35000               193.95000 
2  unknow compound 3     7.410         194.04209         7.610         7.210                  194.24209               193.84209  
3  unknow compound 4     7.434         342.11615         7.634         7.234                  342.31615               341.91615 
4  unknow compound 5     0.756         176.03128         0.956         0.556                  176.23128               175.83128  

print(df2)
                   Name  df2  Molecular Weight  RT [min]
0  β-D-Glucopyranuronic acid         194.04220     7.483
1              α,α-Trehalose         194.10000     7.350
2             Threonylserine         206.08970     8.258
3          Terephthalic acid         166.02595     7.465
4              Sulfuric acid          97.96714     8.909

如果满足 2 个条件,我想将 df2 中的行合并到 df1 中的行。

  1. df2 的RT [min]值在 df1 的 RT [min]-0.2RT [min]+0.2的区间内
  2. AND分子量df2 的值在 df1 的分子量 - 0.2分子量 + 0.2的区间内。

这意味着如果 df2 中的一行满足 df1 中另外两行的条件,则 df1 的行将被复制。

所以 df3 应该看起来

print(df3)
            Name df1  RT [min]+0.2  RT [min]-0.2  Molecular Weight + 0.2   Molecular Weight - 0.2                  Name  df2  Molecular Weight     RT [min]
0  unknow compound 1         7.790         7.390               194.24212                 193.84212  β-D-Glucopyranuronic acid          194.0422       7.483 
1  unknow compound 1         7.790         7.390               194.24212                 193.84212              α,α-Trehalose          194.1000       7.350  
2  unknow compound 2         7.710         7.310               194.35000                 193.95000  β-D-Glucopyranuronic acid          194.0422       7.483
3  unknow compound 3         8.310         7.910               206.30000                 205.90000             Threonylserine          206.0897       8.258 
4  unknow compound 4         7.634         7.234               342.31615                 341.91615                        NaN               NaN         NaN 
5  unknow compound 5         0.956         0.556               176.23128                 175.83128                        NaN               NaN         NaN 

df2 中的第一行满足来自 df1 的未知化合物 1未知化合物 2 的 2 个条件,因此我们在 df3 中有两次。

df2 中的第二行仅满足未知化合物 1 的 2 个条件。

df2 中的第三行仅满足未知化合物 3 的 2 个条件。

所有其他行不满足 df1 中的任何条件。

我尝试根据如何连接列值在一定范围内的两个数据框来做到这一点? 第一个答案

import pandas as pd

df_1 = pd.read_excel (r'D:\CD SandBox\df1.xlsx')
df_2 = pd.read_excel (r'D:\CD SandBox\df2.xlsx')

df2.index = pd.IntervalIndex.from_arrays(df2['RT [min]-0.2'],df2['RT [min]+0.2'],closed='both')
df2['RT [min]'] = df2['RT [min]'].apply( lambda x : df2.iloc[df1.index.get_loc(x)])

但是不知道如何处理第二行代码并收到此错误:

df2['RT [min]'] = df2['RT [min]'].apply( lambda x : df2.iloc[df1.index.get_loc(x)])

Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "C:\Users\BCDD\Anaconda3\envs\PTSD\lib\site-packages\pandas\core\series.py", line 4213, in apply
    mapped = lib.map_infer(values, f, convert=convert_dtype)
  File "pandas\_libs\lib.pyx", line 2403, in pandas._libs.lib.map_infer
  File "<input>", line 1, in <lambda>
  File "C:\Users\BCDD\Anaconda3\envs\PTSD\lib\site-packages\pandas\core\indexes\interval.py", line 730, in get_loc
    raise KeyError(key)
KeyError: 8.258

编辑:尝试使用 merge_asof

根据如何使用额外的共享变量加入具有多个重叠时间戳的两个 DataFrame

df2 = df2.drop(['RT [min]',  'Molecular Weight'], axis=1)
df2['RT [min]']=df2['RT [min]-0.2']
pd.merge_asof(df2[['RT [min]','Name df2']] , df1,on='RT [min]',direction ='forward',allow_exact_matches =True)

... 
   RT [min]           Name df2          Name  df1  Molecular Weight
0     0.556  unknow compound 5      α,α-Trehalose         194.10000
1     7.210  unknow compound 3      α,α-Trehalose         194.10000
2     7.234  unknow compound 4      α,α-Trehalose         194.10000
3     7.310  unknow compound 2      α,α-Trehalose         194.10000
4     7.390  unknow compound 1  Terephthalic acid         166.02595


为表格提供了错误的匹配。

任何想法\提示将不胜感激

选项1

如果您使用的是 pandas 1.2.0,您可以创建两个数据帧的笛卡尔积,然后检查条件。 另外,由于您不需要df1RT [min]Molecular Weight ,我假设您已经删除了它们:

df3 = df1.merge(df2, how = 'cross', suffixes = [None,None])

#check if 'Molecular Weight' is in the interval:
mask1 = df3['Molecular Weight'].ge(df3['Molecular Weight - 0.2']) & df3['Molecular Weight'].le(df3['Molecular Weight + 0.2'])

#check if 'RT [min]' is in the interval
mask2 = df3['RT [min]'].ge(df3['RT [min]-0.2']) & df3['RT [min]'].le(df3['RT [min]+0.2'])

df3 = df3[mask1 & mask2].reset_index(drop = True)

Output:

df3
            Name df1  RT [min]+0.2  RT [min]-0.2  ...                   Name df2  Molecular Weight RT [min]
0  unknow compound 1          7.79          7.39  ...  β-D-Glucopyranuronic acid          194.0422    7.483
1  unknow compound 2          7.71          7.31  ...  β-D-Glucopyranuronic acid          194.0422    7.483
2  unknow compound 2          7.71          7.31  ...              α,α-Trehalose          194.1000    7.350
3  unknow compound 3          7.61          7.21  ...  β-D-Glucopyranuronic acid          194.0422    7.483
4  unknow compound 3          7.61          7.21  ...              α,α-Trehalose          194.1000    7.350

选项 2

由于您的数据相当大,您是否愿意使用生成器以便不加载整个生成的 dataframe。 同样,我假设您从df1中删除了RT [min]Molecular Weight

import numpy as np
from itertools import product

def df_iter(df1,df2):
    for row1, row2 in product(df1.values, df2.values):

        # RT [min]-0.2 <=  RT [min] <=  RT [min]+0.2
        if row1[2] <= row2[2] <= row1[1]:
            
            #Molecular Weight - 0.2 <= Molecular Weight <= Molecular Weight + 0.2
            if row1[4] <= row2[1] <= row1[3]:
                yield np.concatenate((row1,row2))

df3_rows = df_iter(df1,df2)

然后你可以操作这些行:

for row in df3_rows:
    print(row)

Output:

['unknow compound 1' 7.79 7.39 194.24212 193.84212 'β-D-Glucopyranuronic acid' 194.0422 7.483]
['unknow compound 2' 7.71 7.31 194.35 193.95 'β-D-Glucopyranuronic acid' 194.0422 7.483]
['unknow compound 2' 7.71 7.31 194.35 193.95 'α,α-Trehalose' 194.1 7.35]
['unknow compound 3' 7.61 7.21 194.24209 193.84209 'β-D-Glucopyranuronic acid' 194.0422 7.483]
['unknow compound 3' 7.61 7.21 194.24209 193.84209 'α,α-Trehalose' 194.1 7.35]

或者创建一个 dataframe:

df3 = pd.DataFrame(data = list(df3_rows),
      columns = np.concatenate((df1.columns, df2.columns)))

这导致与选项 1 相同的 dataframe。

注意1:请注意 function df_iter的条件中的索引,这些在我的情况下有效。

注意 2:我很确定您的数据与示例df3不匹配。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM