Pandas 如何有效地组合数据帧 我有两个数据帧,df_oth和df_small “ID”列唯一标识df_oth中的每一行 另一方面,在df_small中,每个ID可能具有不止一次的特征

Pandas 如何有效地组合数据帧 我有两个数据帧,df_oth和df_small “ID”列唯一标识df_oth中的每一行 另一方面,在df_small中,每个ID可能具有不止一次的特征,pandas,dataframe,pandas-groupby,Pandas,Dataframe,Pandas Groupby,我正在努力 从df_small中为每个ID提取某些列的内容 将它们转换为列表并封装在字典中 最后,在df_oth上的一个新列中存储相应的ID 在我的第一次迭代中,我将df_行分配给df_oth上的相应单元格,但这太慢了。然后,我修改了下面的代码,将组合值存储在临时数据帧中,然后在最后推送到df_oth。速度快了一点,但仍然,每个1K操作仍然需要大约4个,我有大约100万个唯一ID。所以,我真的很想得到一些关于如何更快地完成这项工作的建议?使用并行化或其他库(如Dask等)不是一个选项,因此,

我正在努力

  • 从df_small中为每个ID提取某些列的内容
  • 将它们转换为列表并封装在字典中
  • 最后,在df_oth上的一个新列中存储相应的ID
在我的第一次迭代中,我将df_行分配给df_oth上的相应单元格,但这太慢了。然后,我修改了下面的代码,将组合值存储在临时数据帧中,然后在最后推送到df_oth。速度快了一点,但仍然,每个1K操作仍然需要大约4个,我有大约100万个唯一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进行的任何引用都非常昂贵,因此,与通过
    frame['Cx']
    提取列相比,
    iloc[:,n:://code>工作得更好。可以在循环之前更改列顺序,以使所需的列与一侧对齐
  • 在每个循环的组元素上执行的
    reset\u index
    drop
    等操作也很昂贵
我没有完整的统计数据,但经过这些简单的修改后,运行时间从预计的~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')