如何有效地组合熊猫数据帧


  • 我有两个数据帧,df_oth和df_small
  • "ID"列唯一标识df_oth中的每一行
  • 另一方面,在df_small中,每个ID可能具有一次以上的特征

我正在尝试

  • 为每个ID从df_small中提取一些列的内容
  • 将它们转换为列表并包装在词典中
  • 最后,将存储在df_oth上对应ID下的一个新列中

在我的第一次迭代中,我将df_row分配给df_oth上的相应单元格,但这太慢了。然后,我修改了下面的代码,将组合的值存储在一个临时数据帧中,然后在最后推送到df_oth。它变得更快了一点,但仍然,每个1K操作仍然需要大约4秒,我有大约1M的唯一ID。所以,我真的很感激一些关于如何更快地做到这一点的建议?使用并行化或Dask等其他库是不可行的,所以,我必须坚持使用Pandas。

sum_t1, sum_t2 = 0,0
ratio = 1000
df_oth.set_index('ID')
df_oth.sort_index()
df_temp = pd.DataFrame(columns=['ID', 'newcol'])
df_temp.set_index('ID')
grps = df_small.groupby('ID')
idx = 0
for grp, frame in grps:
s1 = time.time()
idx += 1
id_no = frame.iloc[0, frame.columns.get_loc('ID')]
df_row = pd.DataFrame({'ID': id_no, 
'newcol': [
{'C1_Arr': frame['C1'], 
'C2_Arr': frame['C2']}
]})
s2 = time.time()
df_temp = df_temp.append(df_row, ignore_index=True)
t1, t2 = (s2 - s1), (time.time() -s2)
sum_t1 += t1
sum_t2 += t2
if idx % ratio == 0:
print(f'{idx}: {ser_no} - {sum_t1} - {sum_t2} - {sum_t1 / sum_t2}')
sum_t1, sum_t2 = 0,0
df_temp.sort_index()
df_oth = pd.merge(df_oth, df_temp, on='ID')

好吧,这需要大量的尝试和错误,但以下是学到的教训

  • 不要在每次迭代中将行推送到数据帧中,而是将行添加到列表中,并在末尾的一行中附加到df
  • 任何通过[]、loc和iloc的引用都非常昂贵,因此,iloc[:, n:]的工作效果要好得多,而不是通过frame['Cx']提取列。列顺序可以在循环之前更改,以保持所需的列与一侧对齐
  • reset_indexdrop对每个循环上的组元素的操作也是昂贵的

我没有完整的统计数据,但经过这些简单的修改,运行时间从预计的~1+h到2分钟。

temp_lst = list()
df_tmp = pd.DataFrame(columns=['ID', 'newcol'])
grps = df_small.groupby('ID')
for grp_name, frame in grps:
temp_lst.append({'ID': grp_name, 'newcol': 
list(frame.iloc[:, 1:].T.to_dict().values())})
df_tmp = df_temp.append(df_row, ignore_index=True)
df_oth = df_oth.merge(df_temp, how='left', on='ID')

最新更新