对照另一个 DataFrame 的列表列检查一个 DataFrame 的列表列
Checking one DataFrame's Column of Lists Against Another DataFrame's Column of Lists
我有 2 个 DataFrame,每个都有一列列表。
我需要检查 df2
中的每个列表,看看 df1
中是否有包含其所有元素的列表。
即。 df2
第 1 行有一个列表 [1,5]
。我需要检查 df1
的所有列表,看看是否有任何列表同时包含 1 和 5。
对于 df2
中具有完全匹配的任何列表,它们会在 df2['bucket']
列中标记为 'clean'
。
我的问题:对于较大的数据集,目前速度非常慢。我希望有人可以提出更快的方法。
import pandas as pd
list1 = [
['a', [1, 5, 10, 14, 15]],
['l', [7, 13, 25, 46, 50]],
['o', [2, 4, 6, 19, 36]],
['d', [1, 19, 24, 26, 29]]]
df1 = pd.DataFrame(list1, columns =['Fruits', 'Values'])
list2 = [
['a', [1, 5]],
['r', [2, 4, 5]],
['e', [2, 9]],
['f', [2, 6, 36]],
['w', [2, 6, 37]],
['a', [24, 29]],
['q', [1, 14, 15]]]
df2 = pd.DataFrame(list2, columns =['Fruits', 'Values'])
df1['bucket'] = ""
list1_row_count = df1.shape[0]
list2_row_count = df2.shape[0]
for x in range(list2_row_count):
break_out = False
for _ in range(list1_row_count):
if break_out == True : break
df1_list = df1['Values'].iloc[_]
df2_list = df2['Values'].iloc[x]
check = all(item in df1_list for item in df2_list)
if check is True:
df2.loc[x, 'bucket'] = 'clean'
break_out = True
else :
df2.loc[x, 'bucket'] = 'mixed'
print(df1)
print('')
print(df2)
你可以尝试使用to_numpy()
,速度相当快:
def process(a, b):
def compare(a, i):
idx = 0
while idx < a.shape[0]:
if all(x in a[idx] for x in i): return 'clean'
idx +=1
return 'mixed'
return [compare(a, i) for i in b]
df2['bucket'] = process(df1.Values.to_numpy(), df2.Values.to_numpy())
Fruits Values bucket
0 a [1, 5] clean
1 r [2, 4, 5] mixed
2 e [2, 9] mixed
3 f [2, 6, 36] clean
4 w [2, 6, 37] mixed
5 a [24, 29] clean
6 q [1, 14, 15] clean
@AloneTogether 的解决方案应该已经显着缩短了代码的运行时间。我认为您可以使用集合操作来进一步改进运行时间。
基本上,您可以将每个子列表转换为一个集合并使用 set.issubset
迭代地检查 df1['Value']
中的任何列表是否是 df2['Value']
中任何列表的子集:
def process(a, b):
def compare(a, i):
for s in a:
if i.issubset(s):
return 'clean'
return 'mixed'
return [compare(a, i) for i in b]
df2['bucket'] = process([*map(set, df1['Values'])], map(set, df2['Values']))
运行时(在您提供的示例中):
你的:
7.08 ms ± 391 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
@AloneTogether:
273 µs ± 19.7 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
我的:
233 µs ± 16.8 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
我有 2 个 DataFrame,每个都有一列列表。
我需要检查 df2
中的每个列表,看看 df1
中是否有包含其所有元素的列表。
即。 df2
第 1 行有一个列表 [1,5]
。我需要检查 df1
的所有列表,看看是否有任何列表同时包含 1 和 5。
对于 df2
中具有完全匹配的任何列表,它们会在 df2['bucket']
列中标记为 'clean'
。
我的问题:对于较大的数据集,目前速度非常慢。我希望有人可以提出更快的方法。
import pandas as pd
list1 = [
['a', [1, 5, 10, 14, 15]],
['l', [7, 13, 25, 46, 50]],
['o', [2, 4, 6, 19, 36]],
['d', [1, 19, 24, 26, 29]]]
df1 = pd.DataFrame(list1, columns =['Fruits', 'Values'])
list2 = [
['a', [1, 5]],
['r', [2, 4, 5]],
['e', [2, 9]],
['f', [2, 6, 36]],
['w', [2, 6, 37]],
['a', [24, 29]],
['q', [1, 14, 15]]]
df2 = pd.DataFrame(list2, columns =['Fruits', 'Values'])
df1['bucket'] = ""
list1_row_count = df1.shape[0]
list2_row_count = df2.shape[0]
for x in range(list2_row_count):
break_out = False
for _ in range(list1_row_count):
if break_out == True : break
df1_list = df1['Values'].iloc[_]
df2_list = df2['Values'].iloc[x]
check = all(item in df1_list for item in df2_list)
if check is True:
df2.loc[x, 'bucket'] = 'clean'
break_out = True
else :
df2.loc[x, 'bucket'] = 'mixed'
print(df1)
print('')
print(df2)
你可以尝试使用to_numpy()
,速度相当快:
def process(a, b):
def compare(a, i):
idx = 0
while idx < a.shape[0]:
if all(x in a[idx] for x in i): return 'clean'
idx +=1
return 'mixed'
return [compare(a, i) for i in b]
df2['bucket'] = process(df1.Values.to_numpy(), df2.Values.to_numpy())
Fruits Values bucket
0 a [1, 5] clean
1 r [2, 4, 5] mixed
2 e [2, 9] mixed
3 f [2, 6, 36] clean
4 w [2, 6, 37] mixed
5 a [24, 29] clean
6 q [1, 14, 15] clean
@AloneTogether 的解决方案应该已经显着缩短了代码的运行时间。我认为您可以使用集合操作来进一步改进运行时间。
基本上,您可以将每个子列表转换为一个集合并使用 set.issubset
迭代地检查 df1['Value']
中的任何列表是否是 df2['Value']
中任何列表的子集:
def process(a, b):
def compare(a, i):
for s in a:
if i.issubset(s):
return 'clean'
return 'mixed'
return [compare(a, i) for i in b]
df2['bucket'] = process([*map(set, df1['Values'])], map(set, df2['Values']))
运行时(在您提供的示例中):
你的:
7.08 ms ± 391 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
@AloneTogether:
273 µs ± 19.7 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
我的:
233 µs ± 16.8 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)