【问题标题】:Optimizing a nested loop in pandas优化熊猫中的嵌套循环
【发布时间】:2021-03-23 00:01:15
【问题描述】:

我有一个包含 2 列的数据框:“VENDOR_ID”和“GL_Transaction_Description”。我想打印 'GL_Transaction_Description' 列中具有“VENDOR_ID”列中任何值的每一行。

VENDOR_ID GL_Transaction_Description
123 HELLO 345
456 BYE 456
987 THANKS 456

此处所需的输出将是“BYE 456”和“THANKS 456”。 我的代码是这样的:

for k in range(len(df)):
    for j in range(len(df)):
        if df['VENDOR_ID'][k] in df['GL_Transaction_Description'][j] and df['VENDOR_ID'][k] != 'nan':
            print(df['GL_Transaction_Description'][j])

但是这个特定的数据帧计数超过 100k 行,并且使用嵌套的 for 循环运行需要很长时间。关于如何使其执行更快的任何想法?我读过使用 numpy 通常会使事情变得更快,但我无法实现它。

【问题讨论】:

  • 我不明白你想要完成什么。您可以发布示例数据和预期结果吗?
  • 我也不知道你想要完成什么,但 OP 应该寻找布尔掩码(如在 ashkangh awnser 中)和 apply 方法。
  • @CFreitas 对不起,我编辑了它
  • 既然你使用了两个循环,我可以假设如果你有第三行:ID=789, GL="Hello 456",这个值也应该返回?
  • @CFreitas 是的,完全正确

标签: python pandas


【解决方案1】:

使用Boolean Mask

v_list = df['VENDOR_ID'].to_list()
mask = list(map((lambda x: any([(y in x) for y in v_list])), df['GL_Transaction_Description']))

print(df['GL_Transaction_Description'][mask])

假设 'VENDOR_ID' 已经在 str 的 dtype 中。如果不是,则将mask = .... 行更改为:

mask = list(map((lambda x: any([(str(y) in x) for y in v_list])), df['GL_Transaction_Description']))

我们可以通过df.apply()axis=1 来做到这一点。但是,list(map())better system performance(执行时间)比 axis=1 上的 df.apply() 多。

输出:

1       BYE 456
2    THANKS 456
Name: GL_Transaction_Description, dtype: object

【讨论】:

  • 很好,但这仅适用于同一行中的匹配元素。我想要存在于整个 VENDOR_ID 列中的匹配元素。 (检查我重新编辑的问题)
  • @JohnMantios 根据您的说明进行了修改。
  • 非常感谢!如果我想检索匹配元素的索引怎么办?
  • @JohnMantios 我添加了链接以供参考,与axis=1 上的apply() 相比,使用list(map()) 的系统性能更好。在某些情况下,它可能快 3 到 4 倍左右。
  • @JohnMantios 如果您只想要索引,请使用df['GL_Transaction_Description'][mask].index
【解决方案2】:

您可以使用boolean Indexing

df.loc[df['GL_Transaction_Description'].isin(df['VENDOR_ID']), 'GL_Transaction_Description']

【讨论】:

    【解决方案3】:

    您可以通过 isin 函数使用布尔索引

    import pandas as pd
    df = pd.DataFrame({'VENDOR_ID': list('abcde') + ['matching_item'],
                      'GL_Transaction_Description': ['trx_descr_' + c for c in list('abcde')] + ['matching_item']})
    df
    
        VENDOR_ID       GL_Transaction_Description
    0   a               trx_descr_a
    1   b               trx_descr_b
    2   c               trx_descr_c
    3   d               trx_descr_d
    4   e               trx_descr_e
    5   matching_item   matching_item
    
    df[df.GL_Transaction_Description.isin(df.VENDOR_ID)].GL_Transaction_Description
    
    5    matching_item
    Name: GL_Transaction_Description, dtype: object
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-11-01
      • 2023-02-04
      • 1970-01-01
      • 2021-01-21
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多