【问题标题】:Pandas lambda apply in two columns that are lists in an efficient wayPandas lambda 以有效的方式应用于两列列表
【发布时间】:2020-11-09 11:12:14
【问题描述】:

我有一个这样的数据集:

d = pd.DataFrame({
    'users_list':[["us1",  "us2", "us3", "us5", "us5"], ['us2', "us3", 'us2']], 
    'users_tuples': [[('us1', 'us2'), ('us2', 'us3'), ('us5', 'us1'), ('us5', 'us1')], [('us2', 'us3'), ('us3', 'us2')]]})

首先我得到一个不重复的所有用户列表,如下所示:

all_users = sorted(list(set(sum([x for x in d['users_list']],[]))))

然后我有以下内容:

for us in all_users:
   d[us] = d.apply(lambda x :  [1 if (a, us) in x['users_tuples'] else 0 for a in x['users_list']], 1)

但我得到的答案是一个列表:

us1              us2              us3             us5
[0, 0, 0, 1, 1] [1, 0, 0, 0, 0] [0, 1, 0, 0, 0] [0, 0, 0, 0, 0]
[0, 0, 0]        [0, 1, 0]      [1, 0, 1]       [0, 0, 0]

我想要这些中每一个的总和,所以它将是:

us1 us2 us3 us5
2   1   1   0
0   1   2   0

我知道我可以做到这一点:

for us in all_users:
       d[us] = d.apply(lambda x :  sum([1 if (a, us) in x['users_tuples'] else 0 for a in x['users_list']]), 1)

但我认为所有这些转换都不是有效的,我想知道是否有更有效的方法来完成它们。

【问题讨论】:

  • 你能添加预期的输出吗?
  • 是的,我已经更新了更多细节!

标签: arrays python-3.x pandas algorithm performance


【解决方案1】:

您可以尝试使用collection.Counter 来计算出现次数,然后将其转换为数据框并使用df.reindex 并使用df.fillna 用0 填充缺失值

def f(x):
    l = map(itemgetter(1), x) # equivalent to `(v for _,v in x)` or `map(lambda v: v[1], x)`
    return Counter(l)

(pd.DataFrame(d['users_tuples'].map(f).tolist()).
    reindex(set(chain.from_iterable(d['users_list'])),axis=1).fillna(0))

   us2  us5  us3  us1
0    1  0.0    1  2.0
1    1  0.0    1  0.0

【讨论】:

  • 您好,感谢您的回复!你能解释一下为什么这样更有效率吗?
  • 在数据帧上使用for-loop 比使用矢量化解决方案要慢得多。并且sum([x for x in d['users_list']],[]) 不要使用这个扁平化列表,它的效率非常低并且是二次运行时。使用chain/ chain.from_iterable。然后您使用timeit 测试自己;)read about it here @CatarinaNogueira
  • 并且df.apply 超过轴 1 也是低效的,应该作为最后的手段使用。阅读有关它的更多信息here posted by cs95,您在每次迭代中都使用df.apply@CatarinaNogueira
猜你喜欢
  • 2016-02-22
  • 2017-06-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-15
  • 2013-11-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多