更快的替代方案

时间:2018-07-03 08:16:53

标签: python list pandas lambda apply

我知道这个话题已经解决了上千次。但是我找不到解决办法。

我试图计算列表(df2.list2)的列中出现列表(df1.list1的每一行)的频率。所有列表仅包含唯一值。 List1包含约300.000行,list2包含30.000行。

我有一个有效的代码,但是它的运行速度非常慢(因为我正在使用iterrows)。我也尝试过itertuples(),但它给了我一个错误(“要解压缩的值太多(预期2)”)。我在网上发现了一个类似的问题:Pandas counting occurrence of list contained in column of lists。在提到的情况下,此人仅考虑一列列表中出现一个列表。但是,我无法解决问题,因此将df1.list1中的每一行都与df2.list2进行了比较。

那是我的列表的样子(简化):

df1.list1

0   ["a", "b"]
1   ["a", "c"]
2   ["a", "d"]
3   ["b", "c"]
4   ["b", "d"]
5   ["c", "d"]


df2.list2

0    ["a", "b" ,"c", "d"]
1    ["a", "b"] 
2    ["b", "c"]
3    ["c", "d"]
4    ["b", "c"]

我想提出的内容:

df1

    list1         occurence   
0   ["a", "b"]    2
1   ["a", "c"]    1
2   ["a", "d"]    1
3   ["b", "c"]    3
4   ["b", "d"]    1
5   ["c", "d"]    2

那是我到目前为止所得到的:

for index, row in df_combinations.iterrows():
    df1.at[index, "occurrence"] = df2["list2"].apply(lambda x: all(i in x for i in row['list1'])).sum()

有人建议我如何加快速度吗?预先感谢!

1 个答案:

答案 0 :(得分:1)

这应该快得多:

<html lang="en">
<head>
<title>title</title>
<meta charset="utf-8" />
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" >
</head>
<body>
<div>
<button>
<span class="glyphicon glyphicon-chevron-up"></span>
</button>
</div>
<div>
<button>
<span class="glyphicon glyphicon-chevron-up"></span>
<img src="https://upload.wikimedia.org/wikipedia/commons/c/ce/Transparent.gif" alt="UP button">
</button>
</div>
</body>
</html>

使用您的方法:

df = pd.DataFrame({'list1': [["a","b"],
                             ["a","c"],
                             ["a","d"],
                             ["b","c"],
                             ["b","d"],
                             ["c","d"]]*100})
df2 = pd.DataFrame({'list2': [["a","b","c","d"],
                              ["a","b"], 
                              ["b","c"],
                              ["c","d"],
                              ["b","c"]]*100})

list2 = df2['list2'].map(set).tolist()

df['occurance'] = df['list1'].apply(set).apply(lambda x: len([i for i in list2 if x.issubset(i)]))
  

1个循环,每个循环最好3:3.98 s   使用我的:

%timeit for index, row in df.iterrows(): df.at[index, "occurrence"] = df2["list2"].apply(lambda x: all(i in x for i in row['list1'])).sum()
  

10个循环,每个循环最好3:29.7毫秒

请注意,我已将列表的大小增加了100倍。

编辑

这似乎更快:

%timeit list2 = df2['list2'].map(set).tolist();df['occurance'] = df['list1'].apply(set).apply(lambda x: len([i for i in list2 if x.issubset(i)]))

时间:

list2 = df2['list2'].sort_values().tolist()
df['occurance'] = df['list1'].apply(lambda x: len(list(next(iter(())) if not all(i in list2 for i in x) else i for i in x)))
  

100个循环,每个循环最好3:14.8毫秒