【问题标题】:Python - Aggregate on week of the month basis and comparePython - 在每月的一周进行聚合并进行比较
【发布时间】:2020-04-20 21:05:41
【问题描述】:

我正在处理一个小型 csv 数据集,其中的值按每月的一周发生索引。我想要的是按顺序聚合所有周,除了当前周或最后一列,以计算剩余数据的每周平均值(...10/1 + 11/1 + 12/1.. 的平均值)获取第 1 周的数据)。

数据以这种格式提供:

char 2019/11/1 2019/11/2 2019/11/3 2019/11/4 2019/11/5 2019/12/1 2019/12/2 2019/12/3 2019/12/4 2019/12/5 2020/1/1
A    1477      1577      1401      773       310       1401      1464      1417      909       712 289   
B    1684      1485      1220      894       297       1618      1453      1335      920       772 275
C    37        10        1         3         6         17        6         6         3         2    1
D    2041      1883      1302      1136      376       2175      1729      1167      960       745  278
E    6142      5991      5499      3883      1036      4949      6187      5760      3974      2339 826
F    842       846       684       462       140       789       802       134       386       251  94

此列 (2020/1/1) 稍后将用于与第一周的所有聚合值的平均值进行比较。所需的输出是这样的:

char    W1      W2      W3      W4      W5      2020/1/1
A       1439    1520.5  1409    841     511     289
B       1651    1469    1277.5  907     534.5   275
C       27      8       3.5     3       4       1
D       2108    1806    1234.5  1048    560.5   278
E       5545.5  6089    5629.5  3928.5  1687.5  826
F       815.5   824     409     424     195.5   94

在这种情况下是否可以使用滚动或重新采样?关于如何做到这一点的任何想法?

【问题讨论】:

    标签: python pandas csv date aggregate


    【解决方案1】:

    我相信你需要 DataFrame.resample 周数:

    df = df.set_index(['char', '2020/1/1'])
    df.columns = pd.to_datetime(df.columns, format='%Y/%m/%d')
    
    df = df.resample('W', axis=1).mean()
    print (df)
                    2019-11-03  2019-11-10  2019-11-17  2019-11-24  2019-12-01  \
    char 2020/1/1                                                                
    A    289       1485.000000       541.5         NaN         NaN      1401.0   
    B    275       1463.000000       595.5         NaN         NaN      1618.0   
    C    1           16.000000         4.5         NaN         NaN        17.0   
    D    278       1742.000000       756.0         NaN         NaN      2175.0   
    E    826       5877.333333      2459.5         NaN         NaN      4949.0   
    F    94         790.666667       301.0         NaN         NaN       789.0   
    
                   2019-12-08  
    char 2020/1/1              
    A    289          1125.50  
    B    275          1120.00  
    C    1               4.25  
    D    278          1150.25  
    E    826          4565.00  
    F    94            393.25 
    

    编辑:如果想将每个月的前 7 天分组为不同的组,请使用:

    df = df.set_index(['char', '2020/1/1'])
    c = pd.to_datetime(df.columns, format='%Y/%m/%d')
    df.columns = [f'{y}/{m}/W{w}' for w,m,y in zip((c.day - 1) // 7 + 1,c.month, c.year)]
    df = df.groupby(df.columns, axis=1).mean()
    print (df)
                   2019/11/W1  2019/12/W1
    char 2020/1/1                        
    A    289           1107.6      1180.6
    B    275           1116.0      1219.6
    C    1               11.4         6.8
    D    278           1347.6      1355.2
    E    826           4510.2      4641.8
    F    94             594.8       472.4
    

    EDIT1:对于 dy 年和日分组,请使用 DatetimeIndex.strftime:

    df = df.set_index(['char', '2020/1/1'])
    df.columns = pd.to_datetime(df.columns, format='%Y/%m/%d').strftime('%d-%Y')
    
    df = df.groupby(df.columns, axis=1).mean()
    print (df)
                   01-2019  02-2019  03-2019  04-2019  05-2019
    char 2020/1/1                                             
    A    289        1439.0   1520.5   1409.0    841.0    511.0
    B    275        1651.0   1469.0   1277.5    907.0    534.5
    C    1            27.0      8.0      3.5      3.0      4.0
    D    278        2108.0   1806.0   1234.5   1048.0    560.5
    E    826        5545.5   6089.0   5629.5   3928.5   1687.5
    F    94          815.5    824.0    409.0    424.0    195.5
    

    【讨论】:

    • 很好,我的解决方案几乎相同,但不会重新索引缺少的几周
    • @jezrael 对 w 的重新采样将低于每周频率。我输入的是月份中的第几周,因此 2019/11/3 表示日期范围 2019/11/14 到 2019/11/21 的数据值,2019/12/5 将涵盖 2019/12/28 到2019/12/31.
    • @jezrael 11 月的第 1 周的值为 1477,12 月的第 1 周的值为 1401,因此第 1 周的平均值应为 1439。目前为 1485。
    • @PukarAcharya - 所以你需要按天和年分组而不需要几个月?答案已编辑。
    【解决方案2】:

    这是使用groupby的一种方式:

    m= df.set_index(['char', '2020/1/1']).rename(columns=lambda x: pd.to_datetime(x))
    m.groupby(m.columns.week,axis=1).mean().add_prefix('W_').reset_index()
    

      char  2020/1/1         W_44    W_45    W_48     W_49
    0    A       289  1485.000000   541.5  1401.0  1125.50
    1    B       275  1463.000000   595.5  1618.0  1120.00
    2    C         1    16.000000     4.5    17.0     4.25
    3    D       278  1742.000000   756.0  2175.0  1150.25
    4    E       826  5877.333333  2459.5  4949.0  4565.00
    5    F        94   790.666667   301.0   789.0   393.25
    

    【讨论】:

    • 实际上直接相对于 w 重新采样不会产生我正在寻找的输出。这里的日期列是按月的每周索引的,因此 1-28 天将分别分组在第 1-4 周下,每个有 7 天栏,而该月的剩余天数将在第 5 周下分组。在我的所需输出,W1 是 2019/11/1(11 月第一周)和 2019/12/1(12 月第一周)的平均值,W5 是 2011/11/5(11 月第五周)和 2011/12 的平均值/5(12 月的第 5 周)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-09
    • 1970-01-01
    相关资源
    最近更新 更多