知道 Python 中的 2 个列表之间是否存在共同项目的最快方法?
fatest way to know if there is common items between 2 lists in Python?
我目前正在 python 上处理 2 Pandas DataFrame。我有一个很大的 DataFrame (135000 Observations),我正在努力寻找一种优化的算法,使我能够更有效地执行微积分。我的第一个数据库 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
是的,检查集合交叉点的工作需要三秒钟。 :)
我目前正在 python 上处理 2 Pandas DataFrame。我有一个很大的 DataFrame (135000 Observations),我正在努力寻找一种优化的算法,使我能够更有效地执行微积分。我的第一个数据库 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
是的,检查集合交叉点的工作需要三秒钟。 :)