对多级表/数据应用函数



我在工作中遇到了问题。我有表:

import pandas as pd
import numpy as np
level1 = pd.DataFrame(list(zip(['a', 'b', 'c'], [3, 'x', 'x'])),
columns=['name', 'value'])
   name value
0   a   3
1   b   x
2   c   x

我想对value列求和,但它包含"x"。因此,我将不得不使用第二个表来计算"x"s:

level2 = pd.DataFrame(list(zip(['b', 'b', 'c', 'c', 'c'], ['b1', 'b2', 'c1', 'c2', 'c3'], [5, 7, 2, 'x', 9])), 
columns=['name', 'sub', 'value'])
  name  sub value
0   b   b1  5
1   b   b2  7
2   c   c1  2
3   c   c2  x
4   c   c3  9

我应该把b1, b2加起来,得到level1表(x=12)中b的x。但是对于c,有" x ",所以有第三层表:

level3 = pd.DataFrame(list(zip(['c', 'c', 'c'], ['c1', 'c2', 'c3'], [2, 4, 9])), 
columns=['name', 'sub', 'value'])
  name  sub value
0   c   c1  2
1   c   c2  4
2   c   c3  9

现在,我们可以得到level1表中value列的和值。

我的问题是:我们可以用一个函数来计算它吗?如果有更多关卡,我们如何循环它们直到没有"x"?

可以将level2level3组合使用

使用combine_firstreplace的方法:

from functools import reduce
l1 = level1.assign(sub=level1['name']+'1').replace('x', np.nan).set_index(['name', 'sub'])
l2 = level2.replace('x', np.nan).set_index(['name', 'sub'])
l3 = level3.replace('x', np.nan).set_index(['name', 'sub'])
reduce(lambda x, y: x.combine_first(y), [l3,l2,l1]).groupby(level=0).sum()

输出:

      value
name       
a       3.0
b      12.0
c      15.0

完整例子:

import pandas as pd
import numpy as np
level1 = pd.DataFrame(list(zip(['a', 'b', 'c'], [3, 'x', 'x'])),
                      columns=['name', 'value'])
level2 = pd.DataFrame(list(zip(['b', 'b', 'c', 'c', 'c'], 
                               ['b1', 'b2', 'c1', 'c2', 'c3'], 
                               [5, 7, 2, 'x', 9])), 
                      columns=['name', 'sub', 'value'])
level3 = pd.DataFrame(list(zip(['c', 'c', 'c'], 
                               ['c1', 'c2', 'c3'], 
                               [2, 4, 9])),
                      columns=['name', 'sub', 'value'])
from functools import reduce
l1 = level1.assign(sub=level1['name']+'1')
           .replace('x', np.nan)
           .set_index(['name', 'sub'])
l2 = level2.replace('x', np.nan)
           .set_index(['name', 'sub'])
l3 = level3.replace('x', np.nan)
           .set_index(['name', 'sub'])
out = reduce(lambda x, y: x.combine_first(y), 
             [l3,l2,l1]).groupby(level=0).sum()
print(out)

一个选项是merge(实际上是多个merge)和groupby的组合:

(level2
.merge(level3, on = ['name', 'sub'], how = 'left', suffixes = (None, '_y'))
.assign(value = lambda df: np.where(df.value.eq('x'), df.value_y, df.value))
.groupby('name', as_index = False)
.value
.sum()
.merge(level1, on = 'name', how = 'right', suffixes = ('_x',None))
.assign(value = lambda df: np.where(df.value.eq('x'), df.value_x, df.value))
.loc[:, ['name', 'value']]
)
  name value
0    a     3
1    b  12.0
2    c  15.0

最新更新