Pandas计算是指使用最接近当前日期的值的组

时间:2016-11-21 22:34:56

标签: python pandas

我试图计算所有类别的日期均值。但是,每个类别(示例中称为mygroup)都没有每个日期的值。我想在pandas中使用apply来计算每个日期的平均值,使用小于或等于当前日期的最接近日期填充值。例如,如果我有:

pd.DataFrame({'date':['1','2','3','6','1','3','4','5','1','2','3','4'],
          'mygroup':['a','a','a','a','b','b','b','b','c','c','c','c'],
          'myval':[10,20,30,40,50,60,70,80,90,100,110,120]})

   date mygroup myval
0   1   a   10
1   2   a   20
2   3   a   30
3   6   a   40
4   1   b   50
5   3   b   60
6   4   b   70
7   5   b   80
8   1   c   90
9   2   c   100
10  3   c   110
11  4   c   120

计算date == 1的平均值应该等于(10 + 50 + 90)/3 = 50,这可以通过典型的平均应用组日期来完成。但是,对于date == 6,我想使用每个mygroup的最后已知值。 date == 6的平均值将计算为

(40 + 80 + 120)/3 = 80由于a的值为date == 6 40b的值不是date == 6,所以最后已知值为date == 580c的最后已知值为date == 4 120。最终结果应如下所示:

date meanvalue
1    50
2    56.67
3    66.67
4    73.33
5    76.67
6    80

是否可以使用groupby计算日期的平均值,并以这种方式应用,使用每个mygroup并填写最后一个已知值,如果当前日期没有值?这必须在数千个日期和数万个类别中完成,因此应避免使用循环。

2 个答案:

答案 0 :(得分:3)

df.set_index(['mygroup', 'date']).unstack().ffill(axis=1) \
  .stack().groupby(level=1).mean()

          myval
date           
1     50.000000
2     56.666667
3     66.666667
4     73.333333
5     76.666667
6     80.000000
  • 将索引设置为键列
  • 将日期级别拆分为列
  • 水平填补空白 - 你知道一个密集的矩阵,你可以反对
  • 将日期放回
  • 按日期分组,即您期望的输出
  • 应用数学 - 这里你想要一个意思

要记住,对于许多问题有用的关键点是堆叠/取消堆叠/旋转等...... " rubikscubing" 您的数据框始终如一填充稀疏格式的空白(比如你必须开始的柱状格式)到一个密集的NAs中。

因此,如果您能够使用全密集矩阵轻松进行计算,那么我建议您始终首先关注获得密集矩阵,以便之后可以进行简单的数学运算。

答案 1 :(得分:0)

您可以将所有隐式缺失值转换为显式,并使用前向填充方案填充缺失值,然后按平均值进行正常分组:

from itertools import product
import pandas as pd

# get all combinations of date and mygroup using product function from itertools
all_combinations = list(product(df.date.drop_duplicates(), df.mygroup.drop_duplicates()))

# convert implicit missing values to explicit missing values by merging all combinations 
# with original data frame
df1 = pd.merge(df, pd.DataFrame.from_records(all_combinations, 
                                             columns = ['date', 'mygroup']), 'outer')

# fill missing date values with previous date values within each group
df1.sort_values(['mygroup', 'date']).ffill().groupby('date').mean()

#       myval
#date   
#1  50.000000
#2  56.666667
#3  66.666667
#4  73.333333
#5  76.666667
#6  80.000000