【问题标题】:Speed up for-loop that creates a new column using .loc into a faster method?将使用 .loc 创建新列的 for 循环加速到更快的方法中?
【发布时间】:2021-06-24 13:17:21
【问题描述】:

我一直在使用以下方法根据满足多个列表中的多个条件的每一行为新列分配值。它适用于小型 dfs...但是一旦我处理更大的数据,就需要很长时间。

for i, j, k in zip(list1, list2, list3):
    df.loc[((df['foo'] == i) & (df['bar'] == j)),'new_column'] = k

示例数据:

list1 = ['a', 'a', 'e', 'f', 'c']
list2 = [3, 4, 5, 3, 2]
list3 = ['yellow', 'green', 'blue', 'purple', 'orange', 'black']

df = pd.dataframe({'foo': ['a', 'b', 'c', 'd', 'e', 'f', 'c'], 
                   'bar': [3, 2, 2, 4, 5, 3, 2]})

所以基本上对于新专栏,我需要:

  • 第一行标记为黄色(因为 list1=a & list2=3)
  • 第三行标记为黑色(因为 list1=c & list2=2)
  • 第 5 行标记为蓝色(因为 list1=e & list2=5)
  • 第 6 行标记为橙色(因为 list1=f & list2=3)
  • 第 7 行标记为黑色(因为 list1=c & list2=2)

所有列表的长度相同。我已经在 Stack 中搜索了更好的选项,因此我知道一个选项是列表理解(或其他选项),但不确定如何将其与 .loc 结合并创建一个新列。

提前感谢您的帮助!

【问题讨论】:

  • list* 变量的大小如何?
  • 所有列表的长度相同(它们只是来自不同 df 的 3 列)。 :)
  • 是的,我的意思是list1 的长度是多少?我正在尝试查看您需要运行多少循环以及您将拥有多少组合。
  • 也许你可以展示示例数据框,然后说明你做了什么以及你想要什么得到准确的答案,也许你根本不需要 for 循环,因为它可以使用 pandas internal 完成功能。
  • 代码不正确。请正确申报清单。对于字符串,请使用 " 引号

标签: python pandas loops list-comprehension


【解决方案1】:

想法是将zipDataFrame 构造函数一起使用,因此可以将DataFrame.merge 与左连接一起使用:

df1 = pd.DataFrame(zip(list1, list2, list3), columns=['foo','bar','new_column'])
print (df1)
  foo  bar new_column
0   a    3     yellow
1   a    4      green
2   e    5       blue
3   f    3     purple
4   c    2     orange

df = df.merge(df1, how='left', on=['foo','bar'])
print (df)
  foo  bar new_column
0   a    3     yellow
1   b    2        NaN
2   c    2     orange
3   d    4        NaN
4   e    5       blue
5   f    3     purple
6   c    2     orange

【讨论】:

    【解决方案2】:

    您似乎正在尝试在此处实现与联接操作等效的操作。以下应该给您相同的结果并使用数据帧操作,因此可能比遍历列表更快。

    (我从您的示例中删除了“紫色”)

    list3 = ['yellow', 'green', 'blue', 'orange', 'black']
    

    从您的列表中构建一个数据框并加入条件(foo = i & bar = j):

    joiner = pd.DataFrame({"i": list1, "j": list2, "k": list3})
    df.join(joiner.set_index(["i", "j"]), on=["foo", "bar"])
    

    给予:

      foo  bar       k
    0   a    3  yellow
    1   b    2     NaN
    2   c    2   black
    3   d    4     NaN
    4   e    5    blue
    5   f    3  orange
    6   c    2   black
    

    请注意,如果您有重复的匹配项,则每个 (i, j) 匹配项都会有一个重复的 (foo, bar) 行。您需要对数据帧进行重复数据删除以获得与循环代码相同的结果,并且连接的数据帧可能会变得非常大。我猜想,因为你的代码总是会覆盖任何重复的,这并不常见?

    【讨论】:

      猜你喜欢
      • 2020-10-20
      • 2017-08-16
      • 2012-07-29
      • 2019-03-21
      • 1970-01-01
      • 2015-10-14
      • 2022-10-07
      • 2022-01-24
      • 2017-03-24
      相关资源
      最近更新 更多