@TonyTang 的上述回答完美无缺,但它使用的是 python itertools(而不是改进 python 循环的矢量化解决方案),
我发现使用numpy 和pandas 的实现速度更快:
实施:
def find_unique_perms_vectorized(df):
df_size = df['words1'].shape[0]
ind = np.array(np.triu_indices(df_size, 1)).T
words = df['words1'].values[ind]
nums = df['numbers1'].values[ind]
words = words[np.where(nums[:,0]!=nums[:,1])]
new_df = pd.DataFrame(words,columns='wordA wordB'.split())
return new_df.reset_index(drop=True)
比较(请注意,我删除了第一个示例中的 sort 以提供更快的实现):
def find_unique_perms(df):
combs = list(combinations(df['numbers1'].unique(), 2))
refs = df.groupby(['numbers1'])['words1'].agg(list).to_dict()
results = []
for a, b in combs:
for x in refs[a]:
for y in refs[b]:
results.append((x, y))
return pd.DataFrame(results, columns=['wordA', 'wordB']).reset_index(drop=True)
def find_unique_perms_vectorized(df):
df_size = df['words1'].shape[0]
ind = np.array(np.triu_indices(df_size, 1)).T
words = df['words1'].values[ind]
nums = df['numbers1'].values[ind]
words = words[np.where(nums[:,0]!=nums[:,1])]
new_df = pd.DataFrame(words,columns='wordA wordB'.split())
return new_df.reset_index(drop=True)
在以下数据帧中计时后:
np.random.seed(42)
df = pd.DataFrame({'numbers1': np.random.randint(1,100,(1000)), 'words1': ['word' +str(i) for i in range(1000)]})
矢量化实现大约(快8倍):
%timeit find_unique_perms_vectorized(df) : 45.3 ms ± 3.52 ms
@TonyTang 回答:
%timeit find_unique_perms(df) : 377 ms ± 8.38 ms
注意:如果需要进一步解释实施,请通知我