在Pandas的Groupby函数中重命名列名

85
Q1) 我想进行分组、SQL风格的聚合,并重命名输出列:
示例数据集:
    ID     Region  count
0  100       Asia      2
1  101     Europe      3
2  102         US      1
3  103     Africa      5
4  100     Russia      5
5  101  Australia      7
6  102         US      8
7  104       Asia     10
8  105     Europe     11
9  110     Africa     23

我想按照数据集中的IDRegion对观察结果进行分组,并对每个组的count进行求和。所以我使用了类似以下的方法...
>>> print(df.groupby(['ID','Region'],as_index=False).count().sum())

    ID     Region  count
0  100       Asia      2
1  100     Russia      5
2  101  Australia      7
3  101     Europe      3
4  102         US      9
5  103     Africa      5
6  104       Asia     10
7  105     Europe     11
8  110     Africa     23

使用as_index=False后,我能够获得类似SQL的输出。我的问题是,我无法在这里重命名聚合变量count。所以如果在SQL中想要做上述操作,我会这样做:
select ID, Region, sum(count) as Total_Numbers
from df
group by ID, Region
order by ID, Region

如我们所见,在SQL中,我很容易将聚合变量count重命名为Total_Numbers。我想在Pandas中做同样的事情,但在group-by函数中找不到这样的选项。有人可以帮忙吗?
第二个问题(更像是一个观察):
Q2)在Pandas dataframe函数中是否可以直接使用列名而无需将其用引号括起来?
我知道变量名是字符串,所以必须放在引号中,但是我发现如果在dataframe函数之外使用它们作为属性,我们不需要将它们放在引号中。比如df.ID.sum()等等。只有当我们在DataFrame函数中使用它们时,比如df.sort()df.groupby,我们必须将其放在引号中。这实际上有点麻烦,因为在SQL或SAS或其他语言中,我们只需使用变量名而无需加引号。对此有什么建议吗?
请回答两个问题(Q1是主要问题,Q2是意见问题)。
2个回答

97

对于第一个问题,我认为答案应该是:

<your DataFrame>.rename(columns= {'count':'Total_Numbers'})

或者

<your DataFrame>.columns = ['ID', 'Region', 'Total_Numbers']

如果它是Pandas Series,我们就有:
<your Series>.rename("Total_Numbers")

关于第二个问题,我会说答案是否定的。这是可能的,因为python datamodel中提到:

属性引用被翻译成在字典中查找, 例如,m.x 等同于 m.dict["x"]

所以可以像 'df.ID' 这样使用它。

感谢您的回复。重命名功能已经帮了大忙,只是在第一个语法中我想我们需要同时提及columns=..,所以应为<your DataFrame>.rename(columns={'count':'Total_Numbers'}),否则它会默认为索引,并且不会更改列名。第二个语法可以完美运行,但如果只需要重命名一个或两个变量,那么我认为第一个语法更方便,而不是在第二个语法中提及所有变量名称。我本来希望groupby有一些东西可以使用,但看起来并没有。另外我理解pandas df是一个内置的字典类型。希望Panda能够更加灵活。 - Baktaawar

45

目前(截至版本0.20),在对分组操作进行更改列名的方法是链接rename方法。有关详细信息,请参见文档中的此弃用说明

从pandas版本0.20开始已弃用

这是谷歌搜索中的第一个结果,尽管最佳答案可行,但实际上并没有回答问题。有一个更好的答案和一个关于将字典传递给agg方法的完整功能的github讨论

这些答案不幸的是不存在于文档中,但是分组、聚合然后重命名列的一般格式使用字典套字典。外部字典的键是要聚合的列名。内部字典具有以新列名为键、以聚合函数为值的键值对。

在进入正题之前,让我们创建一个四列的DataFrame。

df = pd.DataFrame({'A' : list('wwwwxxxx'), 
                   'B':list('yyzzyyzz'), 
                   'C':np.random.rand(8), 
                   'D':np.random.rand(8)})

   A  B         C         D
0  w  y  0.643784  0.828486
1  w  y  0.308682  0.994078
2  w  z  0.518000  0.725663
3  w  z  0.486656  0.259547
4  x  y  0.089913  0.238452
5  x  y  0.688177  0.753107
6  x  z  0.955035  0.462677
7  x  z  0.892066  0.368850

假设我们想要按列 A、B 进行分组,并使用 meanmedian 聚合列 C,并使用 max 聚合列 D。以下代码可以实现此操作。

df.groupby(['A', 'B']).agg({'C':['mean', 'median'], 'D':'max'})

            D         C          
          max      mean    median
A B                              
w y  0.994078  0.476233  0.476233
  z  0.725663  0.502328  0.502328
x y  0.753107  0.389045  0.389045
  z  0.462677  0.923551  0.923551

这将返回一个具有分层索引的DataFrame。原问题询问如何在同一步骤中重命名列。可以使用字典嵌套字典来实现:

df.groupby(['A', 'B']).agg({'C':{'C_mean': 'mean', 'C_median': 'median'}, 
                            'D':{'D_max': 'max'}})

            D         C          
        D_max    C_mean  C_median
A B                              
w y  0.994078  0.476233  0.476233
  z  0.725663  0.502328  0.502328
x y  0.753107  0.389045  0.389045
  z  0.462677  0.923551  0.923551

这将一次性地重命名所有列,但仍保留分层索引,可以使用df.columns = df.columns.droplevel(0)删除顶层。


3
在2017/2018年后期进行了更改,导致“不支持嵌套重命名器”,原因是GH 15931 - 重命名键的弃用。 - donPablo
不再起作用了,伙计。 - Keivan Ipchi Hagh

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