知道Python中两个列表之间是否有公共项的最快方法?



我目前正在python上编写2 Pandas DataFrame。我有一个大数据框架(135000个观察)),我正在努力寻找一个优化的算法,使我能更有效地进行微积分运算。我的第一个数据库df来自食品,每个观察df.additives列中的list。它含有产品内的所有添加剂。例子:

df.additives[0]=['milkfat-and-nonfat-milk','e200','and-nonfat-milk','milk','natural-flavor','flavor','mono-diglycerides','diglycerides','guar-gum','e412']

第二个数据框是所有不健康添加剂的列表,它们包含在名为

的列表中
high=['e202', 'e407', 'e450', 'e250', 'e341', 'e211', 'e621', 'e200', 'e452', 'e481', 'e340', 'e223', 'e451', 'e338', 'e220', 'e252', 'e339', 'e212', 'e224', 'e491', 'e222', 'e251', 'e407a', 'e492', 'e221', 'e473', 'e210', 'e343', 'e482', 'e228', 'e155', 'e243', 'e226', 'e494', 'e459', 'e493', 'e213']

我的目标是知道df.additives[i]的一个element是否与列表high匹配。如果是True,则在名为df.high的虚拟列中将值1赋给该行。最终目标是识别出哪些食品含有不健康的添加剂,以便以后进行分析(比较等)。我的代码对于少量产品运行良好,但是每次我试图将其应用于我的完整数据集时,代码只运行了10%的样本(大约10000个),并且运行了1个多小时。我知道我的算法架构可能不适合big data样本。我想知道我们是否可以优化它,使一台现代pc机可以在10分钟内执行这个命令?或者我是否使用了优化不足的策略?

我使用的代码如下:

df['high']= np.zeros(len(df)) # create a dummy column with only zeros at first
def common_member(a, b): # define a fct that give True if there is at least one common elelment
a_set = set(a)
b_set = set(b)
if (a_set & b_set):
return True 
else:
return False
i=0
while i<len(df.additives):

if common_member(df.additives.iloc[i],high)==True:
df['high'][i]=1 # change the dummy to 1 in the given row
i=i+1

也可以选择,但没有优化到大样本:

for row in range(len(df.additives)):
list_row = set(df.additives.iloc[row])
if (list_row & set(high)):
df['high'][row]=1

我已经尝试了在堆栈溢出上看到的解决方案来解决一个接近的问题,但是它不适合我的情况(假人留在0):

def common_item(l1, l2):
return list(set(l1) & set(l2))
i=0
while i<len(df.additives):
if common_item(df.additives.iloc[i],high)==True:
df['high'][i]=1
i=i+1

感谢您的支持.

您的主要问题是在pandas中遍历事物可能非常慢。逐行分配可能会导致pandas不得不每行克隆一次整个数据框

那么,让我们在使用df.additives.values迭代它们之前取出所有的值,看看它是如何进行的,我们可以在此过程中创建一个新的布尔值列。

import random
import string
import time
import pandas as pd
start_time = time.time()
high=set(['e202', 'e407', 'e450', 'e250', 'e341', 'e211', 'e621', 'e200', 'e452', 'e481', 'e340', 'e223', 'e451', 'e338', 'e220', 'e252', 'e339', 'e212', 'e224', 'e491', 'e222', 'e251', 'e407a', 'e492', 'e221', 'e473', 'e210', 'e343', 'e482', 'e228', 'e155', 'e243', 'e226', 'e494', 'e459', 'e493', 'e213'])
def make_ingredients():
return [''.join(random.choices(string.ascii_uppercase + string.digits, k=4)) for i in range(1, 100)]
sample_ingredients = make_ingredients()
sample_ingredients.append('e202')
list_of_ingredients = [make_ingredients() for i in range(1, 350000)]
list_of_ingredients.append(sample_ingredients)
checkpoint_time = time.time()
checkpoint_delta = checkpoint_time - start_time
checkpoint_string = time.strftime("%H:%M:%S", time.gmtime(checkpoint_delta))
print(f'Time to create junk data: {checkpoint_string}')
df = pd.DataFrame({'id': range(len(list_of_ingredients)), 'additives': list_of_ingredients})
df["high"] = [len(set(additives).intersection(high)) > 0 for additives in df.additives.values]
print(df)
intersection_delta = time.time() - checkpoint_time
intersection_string = time.strftime("%H:%M:%S", time.gmtime(intersection_delta))
print(f'Time to check for intersections: {intersection_string}')

在我的笔记本电脑上,这会产生:

Time to create junk data: 00:01:21
id                                          additives   high
0            0  [GBI5, 5ZH5, AUSE, GU8C, Z5WJ, NU56, GJ1M, 8EN...  False
1            1  [JPC7, PZ3P, 7PV1, DP6O, 4OZ9, 3UN0, 3116, MXW...  False
2            2  [1RJP, BG6O, PMI9, Y9PD, W9NF, 25A8, QB6C, 490...  False
3            3  [3WCC, 6682, O0BY, JT52, AG8H, 0HKC, VV7N, 5YU...  False
4            4  [ZOGO, 6V4B, NBJZ, 0U93, 0P2G, 8TIH, B15Y, A7I...  False
...        ...                                                ...    ...
349995  349995  [5G6W, QRPL, D3ZH, XIA8, GG8X, H401, 7RU3, 8VY...  False
349996  349996  [ZLJJ, Q8YG, NCE8, ULBT, 6VFU, B24E, EYU5, SM0...  False
349997  349997  [4UJ0, HYD3, UPQ4, 1H8F, 2MKR, LSAM, M7KC, CWF...  False
349998  349998  [LFER, 44CC, 214W, FXU4, 3F4V, UCRD, 8O8F, SBD...  False
349999  349999  [KZJY, 28MA, TDUL, ANBM, SD1A, 69FT, 9TYY, VTF...   True
[350000 rows x 3 columns]
Time to check for intersections: 00:00:03

是的,检查集合路口的工作需要三秒钟。:)

最新更新