vin*_*pal 11 python group-by numpy dataframe pandas
我有一个数据框:
lft rel rgt num
0 t3 r3 z2 3
1 t1 r3 x1 9
2 x2 r3 t2 8
3 x4 r1 t2 4
4 t1 r1 z3 1
5 x1 r1 t2 2
6 x2 r2 t4 4
7 z3 r2 t4 5
8 t4 r3 x3 4
9 z1 r2 t3 4
Run Code Online (Sandbox Code Playgroud)
以及参考词典:
replacement_dict = {
'X1' : ['x1', 'x2', 'x3', 'x4'],
'Y1' : ['y1', 'y2'],
'Z1' : ['z1', 'z2', 'z3']
}
Run Code Online (Sandbox Code Playgroud)
我的目标是将所有出现的 'X1' 替换replacement_dict['X1'],然后计算行的分组总和num。
例如,“x1”、“x2”、“x3”或“x4”的任何实例都将被替换为“X1”等,并且“X1”-“r1”-“t2”组的总和(由上面的重新映射创建的)是 6,等等。
所以我想要的输出是:
replacement_dict = {
'X1' : ['x1', 'x2', 'x3', 'x4'],
'Y1' : ['y1', 'y2'],
'Z1' : ['z1', 'z2', 'z3']
}
Run Code Online (Sandbox Code Playgroud)
我正在使用一个包含 600 万行的数据框和一个包含 60,000 个键的替换字典。使用简单的逐行提取和替换会花费很长时间。
如何有效地扩展这一点(特别是最后一部分)?有人可以推荐熊猫技巧吗?
cot*_*ail 10
反转replacement_dict映射并将map()此新映射到每个 lft 和 rgt 列以替换某些值(例如 x1->X1、y2->Y1 等)。由于 lft 和 rgt 列中的某些值在映射中不存在(例如 t1、t2 等),因此请调用fillna()以填写这些值。1
您还可以对stack()需要替换值的列(lft 和 rgt)调用 map+fillna 并unstack()返回,但因为只有 2 列,对于这种特殊情况可能不值得麻烦。
问题的第二部分可以通过按 lft、rel 和 rgt 列分组后对 num 值求和来回答;所以groupby().sum()应该做到这一点。
# reverse replacement map
reverse_map = {v : k for k, li in replacement_dict.items() for v in li}
# substitute values in lft column using reverse_map
df['lft'] = df['lft'].map(reverse_map).fillna(df['lft'])
# substitute values in rgt column using reverse_map
df['rgt'] = df['rgt'].map(reverse_map).fillna(df['rgt'])
# sum values in num column by groups
result = df.groupby(['lft', 'rel', 'rgt'], as_index=False)['num'].sum()
Run Code Online (Sandbox Code Playgroud)
1 : map()+fillna()可能比您的用例执行得更好,replace()因为在幕后,map()实现了 Cython 优化take_nd()方法,如果有很多值需要替换,则该方法执行得特别好,同时replace()实现replace_list()使用 Python 循环的方法。因此,如果replacement_dict特别大(在您的情况下),性能差异将会很大,但如果replacement_dict很小,replace()可能会优于map()。
请参阅此答案,其中包括显示字典大小和数据帧长度之间交互的不同基准,以了解何时使用replace以及何时使用map+ fillna。
如果你翻转 的键和值replacement_dict,事情就会变得容易得多:
new_replacement_dict = {
v: key
for key, values in replacement_dict.items()
for v in values
}
cols = ["lft", "rel", "rgt"]
df[cols] = df[cols].replace(new_replacement_dict)
df.groupby(cols).sum()
Run Code Online (Sandbox Code Playgroud)
试试这个,我评论了步骤
#reverse dict to dissolve the lists as values
reversed_dict = {v:k for k,val in replacement_dict.items() for v in val}
# replace the values
cols = ['lft', 'rel', 'rgt']
df[cols] = df[cols].replace(reversed_dict)
# filter rows where X1 is anywhere in the columns
df = df[df.eq('X1').any(axis=1)]
# sum the duplicate rows
out = df_filtered.groupby(cols).sum().reset_index()
print(out)
Run Code Online (Sandbox Code Playgroud)
输出:
#reverse dict to dissolve the lists as values
reversed_dict = {v:k for k,val in replacement_dict.items() for v in val}
# replace the values
cols = ['lft', 'rel', 'rgt']
df[cols] = df[cols].replace(reversed_dict)
# filter rows where X1 is anywhere in the columns
df = df[df.eq('X1').any(axis=1)]
# sum the duplicate rows
out = df_filtered.groupby(cols).sum().reset_index()
print(out)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1598 次 |
| 最近记录: |