在多个时间序列上进行分组和汇总

时间:2019-11-30 16:34:22

标签: python pandas pandas-groupby

我是python和pandas的新手,对于如何编写一个简短的函数有一个基本问题,该函数需要一个pd.Dataframe并返回按月分组的相对值。

示例数据:

import pandas as pd
from datetime import datetime
import numpy as np

date_rng = pd.date_range(start='2019-01-01', end='2019-03-31', freq='D')
df = pd.DataFrame(date_rng, columns=['date'])
df['value_in_question'] = np.random.randint(0,100,size=(len(date_rng)))
df.set_index('date',inplace=True)
df.head()

       value_in_question
date    
2019-01-01  40
2019-01-02  86
2019-01-03  46
2019-01-04  75
2019-01-05  35

def absolute_to_relative(df):
    """
    set_index before using
    """
    return df.div(df.sum(), axis=1).mul(100)

relative_df = absolute_to_relative(df)      

relative_df.head()

       value_in_question
date    
2019-01-01  0.895055
2019-01-02  1.924368
2019-01-03  1.029313
2019-01-04  1.678228
2019-01-05  0.783173

与其获取列总和并以此来划分每一行, 我想每个月汇总一下。最终df应该具有相同的 形状和形式,但行值与月份的总和有关。

旧:

             value_in_question
date
"2019-01-01" value/colum_sum * 100

新:

            value_in_question
date
"2019-01-01" value/month_sum * 100

所以我尝试了以下操作,该操作返回value_in_question的NA:

def absolute_to_relative_agg(df, agg):
    """
    set_index before using
    """
    return df.div(df.groupby([pd.Grouper(freq=agg)]).sum(), axis=1)

relative_df = absolute_to_relative(df,'M')

      value_in_question
date    
2019-01-01  NaN
2019-01-02  NaN
2019-01-03  NaN
2019-01-04  NaN
2019-01-05  NaN

3 个答案:

答案 0 :(得分:3)

使用GroupBy.transform代替具有与原始DatatimeIndex相同的def absolute_to_relative_agg(df, agg): """ set_index before using """ return df.div(df.groupby([pd.Grouper(freq=agg)]).transform('sum')) relative_df = absolute_to_relative_agg(df, 'M') 的Series / DateFrame进行聚合,因此可能的划分:

relative_df = df.pipe(absolute_to_relative_agg, 'M')

print (relative_df)
           value_in_question
date                         
2019-01-01           0.032901
2019-01-02           0.045862
2019-01-03           0.048853
2019-01-04           0.008475
2019-01-05           0.041376
                      ...
2019-03-27           0.062049
2019-03-28           0.002165
2019-03-29           0.048341
2019-03-30           0.007937
2019-03-31           0.015152

[90 rows x 1 columns]

调用功能的另一种方法是DataFrame.pipe

ratio

答案 1 :(得分:0)

对于总和,您可以groupby索引月份:

In [31]: month_sum = df.groupby(df.index.strftime('%Y%m')).sum()
    ...: month_sum
    ...:
Out[31]:
        value_in_question
201901               1386
201902               1440
201903               1358

然后您可以使用.map将月份与DataFrame的正确行对齐:

In [32]: map_sum = df.index.strftime('%Y%m').map(month_sum['value_in_question'])
    ...: map_sum
    ...:
Out[32]:
Int64Index([1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386,
            1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386,
            1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1386, 1440, 1440,
            1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440,
            1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440, 1440,
            1440, 1440, 1440, 1440, 1358, 1358, 1358, 1358, 1358, 1358, 1358,
            1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358,
            1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358, 1358,
            1358, 1358],
           dtype='int64')

然后您只需要进行除法:

In [33]: df['value_in_question'].div(map_sum)
Out[33]:
date
2019-01-01    0.012987
2019-01-02    0.018759
2019-01-03    0.000000
2019-01-04    0.056277
2019-01-05    0.019481
                ...
2019-03-27    0.031664
2019-03-28    0.007364
2019-03-29    0.050074
2019-03-30    0.033873
2019-03-31    0.005155
Name: value_in_question, Length: 90, dtype: float64

答案 2 :(得分:0)

Grouper freq ='M'一起使用。

代码是:

relative_df = df.groupby(pd.Grouper(freq='M'))\
    .value_in_question.apply(lambda x: x.div(x.sum()).mul(100))

它返回索引与原始DataFrame中相同的 Series 且值等于当月相对的 value_in_question