Python Pandas:透视表:aggfunc使用concatenate而不是np.size或np.sum

14

我在DataFrame中有一些条目,例如:

name, age, phonenumber
 A,10, Phone1
 A,10,Phone2
 B,21,PhoneB1
 B,21,PhoneB2
 C,23,PhoneC

以下是我想通过数据透视表实现的结果:

 name, age, phonenumbers, phonenocount
 A,10, "Phone1,Phone2" , 2
 B,21,  "PhoneB1,PhoneB2", 2
 C,23, "PhoneC" , 1

我尝试着做一些类似这样的事情:

pd.pivot_table(phonedf, index=['name','age','phonenumbers'], values=['phonenumbers'], aggfunc=np.size)

然而我希望电话号码作为aggfunc的一部分被连接起来。有什么建议吗?


1
这似乎是一个 groupby 的问题而不是 pivot-table。您是否将任何内容放入实际 dataframe 的列中? - ayhan
无法理解你的问题“在实际数据框中,你是否将任何内容放入列中?”。请帮忙提供更多信息。 - Sivaswami Jeganathan
一个数据透视表包含索引、列和值。因此,你可以将某些行转换为列。如果它们仍然保持为行,则可以将其视为分组操作。但由于你使用了数据透视表,我想也许你有一些额外的列没有在问题中包括进来。 - ayhan
3个回答

13

groupby之后可以使用agg函数:

df.groupby(['name', 'age'])['phonenumber'].\
    agg({'phonecount': pd.Series.nunique, 
         'phonenumber': lambda x: ','.join(x)
        }
       )

#               phonenumber  phonecount
# name  age     
#    A   10   Phone1,Phone2           2
#    B   21 PhoneB1,PhoneB2           2
#    C   23          PhoneC           1

或者根据@root和@Jon Clements提供的较短版本:

df.groupby(['name', 'age'])['phonenumber'].\
   agg({'phonecount': 'nunique', 'phonenumber': ','.join})

2
如果你想让代码更加简洁,你可以直接将'nunique'作为字符串写入,而不是使用pd.Series.nunique - root
2
@Psidom,您也可以直接使用','.join而不是lambda... 那么这个代码变成:df.groupby(['name', 'age'])['phonenumber'].agg({'phonecount': 'nunique', 'phonenumber': ','.join}) - Jon Clements
谢谢,这个方法可行。我之前也在尝试使用透视表解决方案。以下是我找到的代码: pd.pivot_table(df,index=['name','age'],aggfunc=[np.size,np.unique]) - Sivaswami Jeganathan
Panda版本0.23.4发出了警告:未来版本将不再支持在序列上使用字典进行聚合操作。另一种避免此问题的解决方案是df.groupby(['name', 'age']).agg({'phonenumber': [('Count', 'nunique'), ('Phonenumber', ','.join)]}) - yoonghm
如果电话号码列表中尚不存在该号码,是否可以将新电话号码添加到 "phonenumber" 中?例如,"Phone2" 是 "Phone1"。 - yoonghm
我明白了:lambda x: ','.join(set(x.tolist())) - yoonghm

3
这篇文章是从这里得到的:https://medium.com/@enricobergamini/creating-non-numeric-pivot-tables-with-python-pandas-7aa9dfd788a7
感谢Enrico Bergamini写了这篇关于Python Pandas非数值数据透视表的文章,我也曾经为此苦恼。
首先定义输入。
df = pd.DataFrame({'name':['a','a','b','b','c'], 
                   'age':[10, 10, 21, 21, 23], 
                   'phonenumber':['phone1', 'phone2', 'phoneb1', 'phoneb2',
                                  'phonec']})

使用pandas的pivot_table函数可以按照你的需求重新进行数据重塑。
temp = pd.pivot_table(df, index=['name', 'age'], values='phonenumber',
                      aggfunc=[len, lambda x: ",".join(str(v) for v in x)])

输出:

                 len         <lambda>
         phonenumber      phonenumber
name age                             
a    10            2    phone1,phone2
b    21            2  phoneb1,phoneb2
c    23            1           phonec

如果您想在列中删除多级索引,请使用以下代码:

temp.columns = temp.columns.droplevel()

在从列索引中删除函数后,您可以轻松地对它们进行重命名。

temp.columns = ['count', 'concat']

新存储的变量为:

          count           concat
name age                        
a    10       2    phone1,phone2
b    21       2  phoneb1,phoneb2
c    23       1           phonec

美妙的简单! - user46147

0

数据透视表使用df作为数据和phone作为索引,并将代码行连接到字符串变量中。在聚合后,我使用列表推导式来重命名结果列。

fp=pd.pivot_table(data=df,index=["Phone"],values=["Code"],aggfunc=[len,  lambda x: ", ".join(str(v) for v in x)])
fp.columns =["# of Codes" if str(column)=="('len', 'NewCode')" else str(column) for column in fp.columns.tolist()]
fp.columns =["Spec Code" if str(column)=="('<lambda>', 'NewCode')" else str(column) for column in fp.columns.tolist()]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接