我们如何使用 pandas 生成最小值、最大值、平均值、中值……作为数据框的新列?

How can we use pandas to generate min, max, mean, median, ...as new columns for the dataframe?

我刚接pandas。我有一个数据框如下:

     DEST  MONTH  PRICE   SOUR     TYPE  YEAR
0   DEST7      8    159  SOUR4  WEEKEND  2015
1   DEST2      9    391  SOUR1  WEEKEND  2010
2   DEST5      5    612  SOUR1  WEEKDAY  2013
3   DEST4     10    836  SOUR4  WEEKEND  2013
4   DEST4      4    689  SOUR3  WEEKEND  2013
5   DEST7      3    862  SOUR4  WEEKDAY  2014
6   DEST4      5    483  SOUR4  WEEKEND  2016
7   DEST2      2    489  SOUR3  WEEKEND  2017
8   DEST4      7    207  SOUR1  WEEKDAY  2012
9   DEST3     11    374  SOUR2  WEEKDAY  2015
10  DEST1      2    959  SOUR2  WEEKEND  2017
11  DEST5     10    969  SOUR3  WEEKDAY  2011
12  DEST8      3    645  SOUR4  WEEKEND  2013
13  DEST6      7    258  SOUR4  WEEKEND  2013
14  DEST8      5    955  SOUR4  WEEKDAY  2010
15  DEST1      3    568  SOUR4  WEEKEND  2013
16  DEST5      5    601  SOUR4  WEEKDAY  2016
17  DEST1      6    159  SOUR3  WEEKDAY  2011
18  DEST3     11    322  SOUR4  WEEKDAY  2013
19  DEST2     10    103  SOUR2  WEEKDAY  2012

我把代码放在下面,你可以随意生成你自己的随机数据帧:

import pandas as pd
import random
import numpy as np

df= pd.DataFrame({"YEAR": np.random.choice([2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017], 20, replace=True),
                  "MONTH": np.random.choice([_ for _ in range(1, 13)], 20, replace=True),
                  "TYPE": np.random.choice(['WEEKDAY', 'WEEKEND'], 20, replace=True),
                  "SOUR": np.random.choice(['SOUR1', 'SOUR2', 'SOUR3', 'SOUR4'], 20, replace=True),
                  "DEST": np.random.choice(['DEST1', 'DEST2', 'DEST3', 'DEST4','DEST5', 'DEST6', 'DEST7', 'DEST8'], 20, replace=True),
                  "PRICE": np.random.choice([_ for _ in range(100, 999)], 20, replace=True)})
print(df)

我想生成最小值、最大值、平均值、中值...作为新列,将这些列添加到数据框中。这是我试过的聚合代码:

aggregation={
         "PRICE":
    {
        "MIN": lambda x: x.min(skipna=True),
        "MAX":lambda x: x.max(skipna=True),
        "MEDIAN":lambda x: x.median(skipna=True),
        "MEAN":lambda x:x.mean(skipna=True)
    }
}

df1=df.groupby(["YEAR","MONTH","TYPE","SOUR","DEST"]).agg(aggregation).reset_index()
df1

但输出根本不计算任何最小值、最大值、中值、平均值:

    YEAR MONTH     TYPE   SOUR   DEST PRICE                 
                                        MIN  MAX MEDIAN MEAN
0   2010     5  WEEKDAY  SOUR4  DEST8   955  955    955  955
1   2010     9  WEEKEND  SOUR1  DEST2   391  391    391  391
2   2011     6  WEEKDAY  SOUR3  DEST1   159  159    159  159
3   2011    10  WEEKDAY  SOUR3  DEST5   969  969    969  969
4   2012     7  WEEKDAY  SOUR1  DEST4   207  207    207  207
5   2012    10  WEEKDAY  SOUR2  DEST2   103  103    103  103
6   2013     3  WEEKEND  SOUR4  DEST1   568  568    568  568
7   2013     3  WEEKEND  SOUR4  DEST8   645  645    645  645
8   2013     4  WEEKEND  SOUR3  DEST4   689  689    689  689
9   2013     5  WEEKDAY  SOUR1  DEST5   612  612    612  612
10  2013     7  WEEKEND  SOUR4  DEST6   258  258    258  258
11  2013    10  WEEKEND  SOUR4  DEST4   836  836    836  836
12  2013    11  WEEKDAY  SOUR4  DEST3   322  322    322  322
13  2014     3  WEEKDAY  SOUR4  DEST7   862  862    862  862
14  2015     8  WEEKEND  SOUR4  DEST7   159  159    159  159
15  2015    11  WEEKDAY  SOUR2  DEST3   374  374    374  374
16  2016     5  WEEKDAY  SOUR4  DEST5   601  601    601  601
17  2016     5  WEEKEND  SOUR4  DEST4   483  483    483  483
18  2017     2  WEEKEND  SOUR2  DEST1   959  959    959  959
19  2017     2  WEEKEND  SOUR3  DEST2   489  489    489  489

如何修改 python 代码以提供正确的输出?谢谢。

还有一个问题,如果我想添加另一列仅按 TYPE、SOUR、DEST(不包括 MONTH 或 YEAR)计算平均价格组,如果我想保留 TYPE 组,如何生成、酸、苦、月、年?我的预期输出:

    YEAR MONTH     TYPE   SOUR   DEST PRICE                 
                                        MIN  MAX MEDIAN MEAN AVG
0   2010     5  WEEKDAY  SOUR4  DEST8   ...  ... ...    ...  500
1   2010     9  WEEKEND  SOUR1  DEST2   ...  ... ...    ...  
2   2011     6  WEEKDAY  SOUR3  DEST5   ...  ... ...    ...  720
3   2011    10  WEEKDAY  SOUR3  DEST5   ...  ... ...    ...  720
4   2012     7  WEEKDAY  SOUR1  DEST4   ...  ... ...    ...  
5   2012    10  WEEKDAY  SOUR2  DEST2   ...  ... ...    ...  
6   2013     3  WEEKEND  SOUR4  DEST1   ...  ... ...    ...  
7   2013     3  WEEKDAY  SOUR4  DEST8   ...  ... ...    ...  500  
8   2013     4  WEEKEND  SOUR3  DEST4   ...  ... ...    ...  
9   2013     5  WEEKDAY  SOUR1  DEST5   ...  ... ...    ...  
10  2013     7  WEEKEND  SOUR4  DEST6   ...  ... ...    ...  
... 

您的代码实际上确实计算了最小值、最大值、中值和平均值。但是,由于您在 5 列上使用 groupby。对于只有 20 行的所有 5 列,2 行包含相同值的可能性很小。

要么增加数据量,让 groupby 实际上将行分组在一起,要么一次在较少的列上进行 groupby。

要添加一个具有 AVG(平均值)的列,仅使用 3 列作为 groupby,请分别对第一个 DataFrame 执行 groupby,然后将它们合并到三列。

df1=df.groupby(["YEAR","MONTH","TYPE","SOUR","DEST"]).agg(aggregation).reset_index()
df2=df.groupby(["TYPE", "SOUR", "DEST"]).agg({"PRICE":{ "avg" : "mean"} } ).reset_index()
df3= pd.merge(df1, df2, on=["TYPE", "SOUR", "DEST"], how='left')

在聚合中应用多个函数

animals = pd.DataFrame({'kind': ['cat', 'dog', 'cat', 'dog'], 'height': [9.1, 6.0, 9.5, 34.0], 'weight': [7.9, 7.5, 9.9, 198.0]})

animals.groupby("kind").agg(
        min_height=pd.NamedAgg(column='height', aggfunc='min'),
        max_height=pd.NamedAgg(column='height', aggfunc='max'),
        average_weight=pd.NamedAgg(column='weight', aggfunc=np.mean),
    )

输出看起来像

      min_height  max_height  average_weight
kind                                        
cat          9.1         9.5            8.90
dog          6.0        34.0          102.75