【问题标题】:Add group specific features to pandas dataframe将组特定功能添加到熊猫数据框
【发布时间】:2019-05-08 22:17:31
【问题描述】:

我有一个时间序列数据框,其中包含数千个加油站 (uuid) 的汽油价格,多年来每天更新几次。

(可通过:git clone https://dev.azure.com/tankerkoenig/tankerkoenig-data/_git/tankerkoenig-data

df = 
datetime,uuid,diesel,e5,e10
2018-01-31 00:01:06+01,c03c846e-64ec-437f-9a52-9eda8088c4b2,1.239,1.419,1.399
2018-01-31 00:03:06+01,6dc575da-3c85-430c-a17a-6efdae0dcf5a,1.249,1.419,1.399

我想添加一个特征列,它告诉每个diesel,e5,e10 的每个uuid(加油站)价格的daily min()max() 值。

因此我添加了一个日期列:

df['date'] = index.date

然后对数据框进行分组:

df.groupby(['uuid','date','datetime']).sum()

                                                                            diesel  e5      e10
                                uuid    date        datetime            
00006210-0037-4444-8888-acdc00006210    2018-01-01  2018-01-01 06:33:06     1.189   1.389   1.369
                                                    2018-01-01 06:39:05     1.189   1.349   1.329

我现在如何添加特定于组的列。 我想使用 GroupBy.apply() 可能是一种方式,但这很慢或不起作用。

def fun(df):
    df['diesel_low'] = df['diesel'].min()
    return df
df.groupby(['uuid','date','datetime']).apply(lambda x: fun(x))

【问题讨论】:

    标签: python pandas pandas-groupby


    【解决方案1】:

    我相信您需要通过GroupBy.agg 聚合,然后在列中展平MultiIndex 并通过DataFrame.reset_index 将索引转换为列:

    print (df)
                                                               uuid  diesel  e5  \
    datetime                                                                      
    2018-01-31 00:01:06+01:00  c03c846e-64ec-437f-9a52-9eda8088c4b2      15   1   
    2018-01-31 00:03:06+01:00  6dc575da-3c85-430c-a17a-6efdae0dcf5a       9   4   
    2018-01-31 00:01:06+01:00  c03c846e-64ec-437f-9a52-9eda8088c4b2      19   1   
    2018-01-31 00:03:06+01:00  6dc575da-3c85-430c-a17a-6efdae0dcf5a      12   9   
    
                               e10  
    datetime                        
    2018-01-31 00:01:06+01:00    4  
    2018-01-31 00:03:06+01:00    1  
    2018-01-31 00:01:06+01:00    5  
    2018-01-31 00:03:06+01:00   12  
    

    df['date'] = df.index.date
    cols = ['diesel','e5','e10']
    df1 = df.groupby(['uuid','date'])[cols].agg([('low', 'min'),('high', 'max')])
    df1.columns = df1.columns.map('_'.join)
    print (df1)
                                                     diesel_low  diesel_high  \
    uuid                                 date                                  
    6dc575da-3c85-430c-a17a-6efdae0dcf5a 2018-01-31           9           12   
    c03c846e-64ec-437f-9a52-9eda8088c4b2 2018-01-31          15           19   
    
                                                     e5_low  e5_high  e10_low  \
    uuid                                 date                                   
    6dc575da-3c85-430c-a17a-6efdae0dcf5a 2018-01-31       4        9        1   
    c03c846e-64ec-437f-9a52-9eda8088c4b2 2018-01-31       1        1        4   
    
                                                     e10_high  
    uuid                                 date                  
    6dc575da-3c85-430c-a17a-6efdae0dcf5a 2018-01-31        12  
    c03c846e-64ec-437f-9a52-9eda8088c4b2 2018-01-31         5  
    

    df = df.join(df1, on=['uuid','date'])
    print (df)
                                                               uuid  diesel  e5  \
    datetime                                                                      
    2018-01-31 00:01:06+01:00  c03c846e-64ec-437f-9a52-9eda8088c4b2      15   1   
    2018-01-31 00:03:06+01:00  6dc575da-3c85-430c-a17a-6efdae0dcf5a       9   4   
    2018-01-31 00:01:06+01:00  c03c846e-64ec-437f-9a52-9eda8088c4b2      19   1   
    2018-01-31 00:03:06+01:00  6dc575da-3c85-430c-a17a-6efdae0dcf5a      12   9   
    
                               e10        date  diesel_low  diesel_high  e5_low  \
    datetime                                                                      
    2018-01-31 00:01:06+01:00    4  2018-01-31          15           19       1   
    2018-01-31 00:03:06+01:00    1  2018-01-31           9           12       4   
    2018-01-31 00:01:06+01:00    5  2018-01-31          15           19       1   
    2018-01-31 00:03:06+01:00   12  2018-01-31           9           12       4   
    
                               e5_high  e10_low  e10_high  
    datetime                                               
    2018-01-31 00:01:06+01:00        1        4         5  
    2018-01-31 00:03:06+01:00        9        1        12  
    2018-01-31 00:01:06+01:00        1        4         5  
    2018-01-31 00:03:06+01:00        9        1        12  
    

    另一种解决方案:

    df['date'] = df.index.date
    cols = ['diesel','e5','e10']
    df1 = df.groupby(['uuid','date'])[cols].transform('max').add_suffix('_high')
    df2 = df.groupby(['uuid','date'])[cols].transform('min').add_suffix('_low')
    
    df = pd.concat([df, df1, df2], axis=1)
    print (df)
                                                               uuid  diesel  e5  \
    datetime                                                                      
    2018-01-31 00:01:06+01:00  c03c846e-64ec-437f-9a52-9eda8088c4b2      15   1   
    2018-01-31 00:03:06+01:00  6dc575da-3c85-430c-a17a-6efdae0dcf5a       9   4   
    2018-01-31 00:01:06+01:00  c03c846e-64ec-437f-9a52-9eda8088c4b2      19   1   
    2018-01-31 00:03:06+01:00  6dc575da-3c85-430c-a17a-6efdae0dcf5a      12   9   
    
                               e10        date  diesel_high  e5_high  e10_high  \
    datetime                                                                     
    2018-01-31 00:01:06+01:00    4  2018-01-31           19        1         5   
    2018-01-31 00:03:06+01:00    1  2018-01-31           12        9        12   
    2018-01-31 00:01:06+01:00    5  2018-01-31           19        1         5   
    2018-01-31 00:03:06+01:00   12  2018-01-31           12        9        12   
    
                               diesel_low  e5_low  e10_low  
    datetime                                                
    2018-01-31 00:01:06+01:00          15       1        4  
    2018-01-31 00:03:06+01:00           9       4        1  
    2018-01-31 00:01:06+01:00          15       1        4  
    2018-01-31 00:03:06+01:00           9       4        1  
    

    【讨论】:

    • 我不会在这里做一个通用的.agg,而是在agg 中将列指定为dict,否则你也会从日期获得最小值和最大值。所以:df.groupby(['uuid', 'date']).agg({'diesel':['min', 'max'], 'e5':['min', 'max'], 'e10':['min', 'max']})
    • 谢谢!以及如何将这个新数据集合并到旧数据集中?我想要的是这些新创建的 min 和 max 列扩展了原始数据框。此外,我如何将命名从_min 更改为_low_max 更改为_high?这可以在命令中完成,还是我需要稍后使用df.rename(columns={..})
    • 解决方案 2 似乎要快得多。你能解释一下吗,我不熟悉transform()
    • @gustavz 它将聚合值填充到与原始数据帧相同大小的数据帧中,因此不需要连接。
    猜你喜欢
    • 2015-03-13
    • 2023-01-27
    • 2016-09-08
    • 1970-01-01
    • 1970-01-01
    • 2021-07-10
    • 1970-01-01
    • 1970-01-01
    • 2014-04-12
    相关资源
    最近更新 更多