Как мы можем использовать pandas для генерации min, max, mean, median в качестве новых столбцов для фрейма данных?

Я просто беру панд. У меня есть следующий фрейм данных:

     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)

Я хочу сгенерировать min, max, mean, median, ... как новые столбцы, добавить эти столбцы в фрейм данных. Это код агрегации, который я пробовал:

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 (не включая МЕСЯЦ ИЛИ ГОД), как сгенерировать, если я хочу сохранить группу TYPE, SOUR, DEST, МЕСЯЦ ГОД? Мой ожидаемый результат:

    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   ...  ... ...    ...  
... 

person Haven Shi    schedule 20.10.2017    source источник
comment
Вы уверены, что хотите сгруппировать по всем этим столбцам? Какие минимальные / максимальные / средние / средние значения вы на самом деле пытаетесь вычислить? Когда вы группируете по всем этим столбцам, вы получаете только одно значение PRICE для каждой группы, поэтому все эти показатели одинаковы.   -  person jack6e    schedule 20.10.2017
comment
о ... вы правы ... потому что моя выборка настолько мала, что каждая группа включает только одну строку ... Спасибо! а вы знаете ответ на второй вопрос?   -  person Haven Shi    schedule 20.10.2017


Ответы (2)


Ваш код действительно вычисляет минимальное, максимальное, среднее и среднее значение. Однако, поскольку вы используете groupby на 5 столбцах. Вероятность того, что 2 строки содержат одинаковые значения для всех 5 столбцов и всего 20 строк, очень мала.

Либо увеличьте объем данных, чтобы groupby фактически группировал строки вместе, либо groupby по меньшему количеству столбцов за раз.

Чтобы добавить столбец с AVG (среднее значение), используя только 3 столбца для groupby, выполните группировку по первому DataFrame отдельно и объедините их по трем столбцам.

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')
person Prikkel    schedule 20.10.2017
comment
это ответ, который я пытаюсь найти. Большое спасибо, Приккель! - person Haven Shi; 20.10.2017

применить несколько функций в вашем агрегате

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
person user702846    schedule 06.02.2021