【发布时间】:2020-10-30 04:53:37
【问题描述】:
我正在尝试在我的工作场所完成一项更大项目的任务,并且我有一个可行的解决方案,但由于解决方案的时间复杂性,它需要很长时间才能完成任务(数据帧的长度是几百万)。这不是一次性任务,必须每天运行。
目标:给定一个包含两列的表:“a”和“b”,其中“a”有单个字符串作为值,“b”有一个字符串列表作为值,合并“b”中的项目的行一行与其他行的“b”中的一个项目匹配,这样合并表中的“a”和“b”都将是一个项目列表。
示例 1:
输入表:
a b
0 1 [a, b, e]
1 2 [a, g]
2 3 [c, f]
3 4 [d]
4 5 [b]
所需输出:
a b
0 [1, 2, 5] [a, b, e, g]
1 [3] [c, f]
2 [4] [d]
示例 2:
输入表:
a b
0 1 [a, b, e]
1 3 [a, g, f]
2 4 [c, f]
3 6 [d, h]
4 9 [b, g, h]
所需输出:
a b
0 [1, 3, 4, 6, 9] [a, b, c, d, e, f, g, h]
我的工作解决方案:
import pandas as pd
def merge_rows(df):
df_merged = pd.DataFrame(columns=df.columns)
matched = False
while len(df) > 0:
if not matched:
x = len(df_merged)
df_merged.loc[x, 'a'] = list(df.iloc[0, 0])
df_merged.loc[x, 'b'] = df.iloc[0, 1]
df = df.iloc[1:, :]
for rm in range(len(df_merged)):
matched = False
right_b_lists_of_lists = df.b.tolist()
df.reset_index(drop=True, inplace=True)
match_index_list = [i for b_part in df_merged.loc[rm, 'b'] for (i, b_list) in enumerate(right_b_lists_of_lists) if b_part in b_list]
df_matches = df.loc[match_index_list]
if len(df_matches) > 0:
df_merged.loc[rm, 'a'] = list(set(df_merged.loc[rm, 'a'] + df_matches.a.tolist()))
df_merged.loc[rm, 'b'] = list(set(df_merged.loc[rm, 'b'] + [item for sublist in df_matches.b.tolist() for item in sublist]))
df = df.drop(df_matches.index)
matched = True
break
return df_merged
df1 = pd.DataFrame({'a': ['1', '2', '3', '4', '5'], 'b': [['a', 'b', 'e'], ['a', 'g'], ['c', 'f'], ['d'], ['b']]})
df1_merged = merge_rows(df1)
print('Original DF:')
print(df1.to_string())
print('Merged DF:')
print(df1_merged.to_string())
df2 = pd.DataFrame({'a': ['1', '3', '4', '6', '9'], 'b': [['a', 'b', 'e'], ['a', 'g', 'f'], ['c', 'f'], ['d', 'h'], ['b', 'g', 'h']]})
df2_merged = merge_rows(df2)
print('Original DF:')
print(df2.to_string())
print('Merged DF:')
print(df2_merged.to_string())
上面的代码打印如下:
Original DF:
a b
0 1 [a, b, e]
1 2 [a, g]
2 3 [c, f]
3 4 [d]
4 5 [b]
Merged DF:
a b
0 [1, 2, 5] [e, b, a, g]
1 [3] [c, f]
2 [4] [d]
Original DF:
a b
0 1 [a, b, e]
1 3 [a, g, f]
2 4 [c, f]
3 6 [d, h]
4 9 [b, g, h]
Merged DF:
a b
0 [4, 3, 6, 9, 1] [e, h, c, g, f, d, b, a]
请注意,上述代码输出中的“a”和“b”中的列表未排序,但这是可以接受的。
考虑到 O(n^2) 的渐近时间复杂度作为解决方案的平均情况,这个解决方案实际上是不可行的,并且无法想出并行化这个多项式解决方案的方法,我需要的 n 的大尺寸每天运行它,我必须在机器上运行它。
对于线性解或可并行多项式解决方案(或更好!)的任何帮助将不胜感激!
首选 Python 解决方案,但我欢迎使用 R / C / C++ / Java / P 的解决方案。
【问题讨论】:
-
我认为这本质上是不相交的集合并集问题(en.wikipedia.org/wiki/Disjoint-set_data_structure)。我没有解决方案,但这个算法可以让你获得更好的时间复杂度。
-
您是否有一个运行测试需要大约 30 秒的数据集?
标签: python algorithm optimization merge time-complexity