根据条件替换并合并 pandas 中的行

2024-01-22

我有一个数据框:

   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

以及参考词典:

replacement_dict = {
    'X1' : ['x1', 'x2', 'x3', 'x4'],
    'Y1' : ['y1', 'y2'],
    'Z1' : ['z1', 'z2', 'z3']
}

我的目标是替换所有出现的replacement_dict['X1']与“X1”,然后将行合并在一起。例如,“x1”、“x2”、“x3”或“x4”的任何实例都将替换为“X1”等。

我可以通过选择包含任何这些字符串的行并将其替换为“X1”来完成此操作:

keys = replacement_dict.keys()
for key in keys:
    DF.loc[DF['lft'].isin(replacement_dict[key]), 'lft'] = key
    DF.loc[DF['rgt'].isin(replacement_dict[key]), 'rgt'] = key

giving:

    lft rel rgt num
0   t3  r3  Z1  3
1   t1  r3  X1  9
2   X1  r3  t2  8
3   X1  r1  t2  4
4   t1  r1  Z1  1
5   X1  r1  t2  2
6   X1  r2  t4  4
7   Z1  r2  t4  5
8   t4  r3  X1  4
9   Z1  r2  t3  4

现在,如果我选择包含“X1”的所有行并将它们合并,我最终应该得到:

    lft rel rgt num
0   X1  r3  t2  8
1   X1  r1  t2  6
2   X1  r2  t4  4
3   t1  r3  X1  9
4   t4  r3  X1  4

因此,三列 ['lft', 'rel', 'rgt'] 是唯一的,而 'num' 列是为每一行添加的。上面的第 1 行:['X1' 'r1' 't2' 6] 是两行 ['X1' 'r1' 't2' 4] 和 ['X1' 'r1' 't2' 2] 的总和。

我可以轻松地对少量行执行此操作,但我正在使用包含 600 万行的数据框和包含 60,000 个键的替换字典。使用简单的逐行提取和替换会花费很长时间。

如何有效地扩展这一点(特别是最后一部分)?有人可以推荐熊猫技巧吗?


Reverse the replacement_dict mapping and map() this new mapping to each of lft and rgt columns to substitute certain values (e.g. x1->X1, y2->Y1 etc.). As some values in lft and rgt columns don't exist in the mapping (e.g. t1, t2 etc.), call fillna() to fill in these values.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()

1: map() + fillna() may perform better for your use case than replace() because under the hood, map() implements a Cython optimized take_nd() method that performs particularly well if there are a lot of values to replace, while replace() implements replace_list() method which uses a Python loop. So if replacement_dict is particularly large (which it is in your case), the difference in performance will be huge, but if replacement_dict is small, replace() may outperform map().

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

根据条件替换并合并 pandas 中的行 的相关文章

随机推荐