如何匹配pandas DataFrame中的多个列以获得" interval"?

时间:2016-09-30 07:54:23

标签: python pandas dataframe match intervals

我有以下pandas DataFrame:

import pandas as pd
df = pd.DataFrame('filename.csv')
print(df)

order    start    end    value    
1        1342    1357    category1
1        1459    1489    category7
1        1572    1601    category23
1        1587    1599    category2
1        1591    1639    category1
....
15        792     813    category13
15        892     913    category5
....

因此,order列包含多个行,然后每行包含startend的范围/间隔。然后每行标有某个value(例如category1,category2等)

现在我有另一个名为key_df的数据框。它基本上是完全相同的格式:

import pandas as pd
key_df = pd.DataFrame(...)
print(key_df)

order    start    end    value    
1        1284    1299    category4
1        1297    1309    category9
1        1312    1369    category3
1        1345    1392    category29
1        1371    1383    category31
....
1        1471    1501    category31
...

我的目标是获取key_df数据框,并检查时间间隔start:end是否与原始数据框df中的任何行匹配。如果是,则df中的此行应标有key_df数据框的value值。

在上面的示例中,数据框df最终会像这样结束:

order    start    end    value        key_value
1        1342    1357    category1    category29
1        1459    1489    category7    category31
....

这是因为如果你看key_df

1        1345    1392    category29
区间1::1345-1392

位于原始1::1342-1357的{​​{1}}区间内。同样,df行:

key_df

对应于1 1471 1501 category31 中的第二行:

df

我不完全确定

(1)如何在pandas中完成这项任务

(2)如何在pandas中有效地扩展它

可以从if语句开始,例如

1        1459    1489    category7    category31

但这并没有利用数据帧结构。然后必须按间隔检查,即类似if df.order == key_df.order: # now check intervals...somehow

我被困住了。什么是匹配"间隔中的多个列的最有效方法"在熊猫? (如果满足此条件,则创建新列很简单)

1 个答案:

答案 0 :(得分:2)

您可以将mergeboolean indexing一起使用,但如果DataFrames很大,则缩放会产生问题:

df1 = pd.merge(df, key_df, on='order', how='outer', suffixes=('','_key'))
df1 = df1[(df1.start <= df1.start_key) & (df1.end <= df1.end_key)]
print (df1)
    order  start   end      value  start_key  end_key   value_key
3       1   1342  1357  category1     1345.0   1392.0  category29
4       1   1342  1357  category1     1371.0   1383.0  category31
5       1   1342  1357  category1     1471.0   1501.0  category31
11      1   1459  1489  category7     1471.0   1501.0  category31

通过评论编辑:

df1 = pd.merge(df, key_df, on='order', how='outer', suffixes=('','_key'))
df1 = df1[(df1.start <= df1.start_key) & (df1.end <= df1.end_key)]
df1 = pd.merge(df, df1, on=['order','start','end', 'value'], how='left')
print (df1)
   order  start   end       value  start_key  end_key   value_key
0      1   1342  1357   category1     1345.0   1392.0  category29
1      1   1342  1357   category1     1371.0   1383.0  category31
2      1   1342  1357   category1     1471.0   1501.0  category31
3      1   1459  1489   category7     1471.0   1501.0  category31
4      1   1572  1601  category23        NaN      NaN         NaN
5      1   1587  1599   category2        NaN      NaN         NaN
6      1   1591  1639   category1        NaN      NaN         NaN
7     15    792   813  category13        NaN      NaN         NaN
8     15    892   913   category5        NaN      NaN         NaN