【问题标题】:How to match multiple columns in pandas DataFrame for an "interval"?如何为“间隔”匹配pandas DataFrame中的多个列?
【发布时间】:2017-02-08 17:31:18
【问题描述】:

我有以下熊猫数据框:

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 落在原始 df 的区间 1::1342-1357 中。同样,key_df 行:

1        1471    1501    category31

对应df中的第二行:

1        1459    1489    category7    category31

我不完全确定

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

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

可以以 if 语句开头,例如

if df.order == key_df.order:
    # now check intervals...somehow

但这并没有利用数据帧结构。然后必须按间隔检查,即(df.start =< key_df.start) && (df.end => key_df.end)

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

【问题讨论】:

    标签: python pandas dataframe match intervals


    【解决方案1】:

    您可以将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
    

    【讨论】:

    • 我注意到这里有一个错误。如果给定行没有value_key,这将被丢弃。出于我们的目的,df 中的所有行都是好的——不应丢弃任何行。如果没有value_key 适用于给定行(即它不属于区间内),则应记录NaN
    • 那么你需要在我的代码中添加merge并左连接吗? df1 = pd.merge(df, df1, on=['order','start','end', 'value'], how='left') ?
    • 感谢您的回答。我应该提到这对于大小约为 100 MB(及以上)的数据帧是不可扩展的。我得到一个MemoryError。任何想法如何使其更具可扩展性?不是合并,而是很多 for 循环?这是错误:File "pandas/src/join.pyx", line 187, in pandas.algos.full_outer_join(pandas/algos.c:61680)File "pandas/src/join.pyx", line 196, inpandas.algos._get_result_indexer (pandas/algos.c:61978)`MemoryError`
    • 我给你发电子邮件。
    • 电子邮件!这对我有什么帮助?
    猜你喜欢
    • 2020-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-04
    相关资源
    最近更新 更多