pandas:通过在所有行(一列)中拆分字符串值和聚合函数进行分组

Izz*_*jal 6 python numpy pandas

如果我有这样的数据集:

id   person_name                       salary
0    [alexander, william, smith]       45000
1    [smith, robert, gates]            65000
2    [bob, alexander]                  56000
3    [robert, william]                 80000
4    [alexander, gates]                70000
Run Code Online (Sandbox Code Playgroud)

如果我们将工资列求和,则将得到316000

我真的想知道,如果我们将这个数据集中拆分名称中的所有薪水加起来(包含相同的字符串值),那么名为“亚历山大·史密斯等”的人(有区别)会赚多少薪水。

输出:

group               sum_salary
alexander           171000 #sum from id 0 + 2 + 4 (which contain 'alexander')
william             125000 #sum from id 0 + 3
smith               110000 #sum from id 0 + 1
robert              145000 #sum from id 1 + 3
gates               135000 #sum from id 1 + 4
bob                  56000 #sum from id 2
Run Code Online (Sandbox Code Playgroud)

如我们所见,sum_salary列的总和与初始数据集不同。都是因为该功能需要重复计算。

我以为它像字符串计数那样看起来很熟悉,但是让我感到困惑的是我们使用聚合函数的方式。我尝试在person_name列中创建一个新的具有不同值的列表,然后卡住了。

任何帮助表示赞赏,非常感谢

jez*_*ael 4

使用列中的列表的解决方案person_name

#if necessary
#df['person_name'] = df['person_name'].str.strip('[]').str.split(', ')

print (type(df.loc[0, 'person_name']))
<class 'list'>
Run Code Online (Sandbox Code Playgroud)

第一个想法是用于在循环中defaultdict存储sumed 值:

from collections import defaultdict

d = defaultdict(int)
for p, s in zip(df['person_name'], df['salary']):
    for x in p:
        d[x] += int(s)

print (d)
defaultdict(<class 'int'>, {'alexander': 171000, 
                            'william': 125000, 
                            'smith': 110000, 
                            'robert': 145000, 
                            'gates': 135000, 
                            'bob': 56000})
Run Code Online (Sandbox Code Playgroud)

进而:

df1 = pd.DataFrame({'group':list(d.keys()),
                    'sum_salary':list(d.values())})
print (df1)
       group  sum_salary
0  alexander      171000
1    william      125000
2      smith      110000
3     robert      145000
4      gates      135000
5        bob       56000
Run Code Online (Sandbox Code Playgroud)

另一种解决方案是按列表和聚合的长度重复值sum

from itertools import chain

df1 = pd.DataFrame({
    'group' : list(chain.from_iterable(df['person_name'].tolist())), 
    'sum_salary' : df['salary'].values.repeat(df['person_name'].str.len())
})

df2 = df1.groupby('group', as_index=False, sort=False)['sum_salary'].sum()
print (df2)
       group  sum_salary
0  alexander      171000
1    william      125000
2      smith      110000
3     robert      145000
4      gates      135000
5        bob       56000
Run Code Online (Sandbox Code Playgroud)