在保留某些列的同时在 groupby 上使用重新采样的最有效方法,同时保留某些列

时间:2021-01-22 13:31:06

标签: python pandas performance datetime time-series

我在形状方面使用了巨大的 DataFrame,我的示例只是一个简化的示例。

让我们假设以下场景:

# we have these two datetime objects as start and end for my data set
first_day = 2020-03-01 00:00:00
last_day = 2020-03-31 23:59:59

# assume we have a big DataFrame df like this with many, many rows:
              datetime   var1   var2  count1  count2
1  2020-03-01 00:00:01    "A"    "B"       1      12
2  2020-03-01 00:00:01    "C"    "C"       2     179
3  2020-03-01 00:00:01    "C"    "D"       1      72
4  2020-03-01 00:00:02    "C"    "E"       4       7
5  2020-03-01 00:00:02    "D"    "E"       2      47
6  2020-03-01 00:00:02    "H"    "F"       1      31
7  2020-03-01 00:00:02  "ABC"  "DEF"       7      74
8  2020-03-01 00:00:03  "ABC"  "DEF"       3      10
...

# I now want to group on this DataFrame like this:
gb = df.groupby([var1, var2])

# what yields me groups like this as an example:
              datetime   var1   var2  count1  count2
7  2020-03-01 00:00:02  "ABC"  "DEF"       7      74
8  2020-03-01 00:00:03  "ABC"  "DEF"       3      10

我现在需要做的是使用给定的 first_daylast_day 以及偏移别名 1S每个 组重新采样,所以我得到了这样的结果每一个:

              datetime   var1   var2  count1  count2
0  2020-03-01 00:00:00  "ABC"  "DEF"       0       0
1  2020-03-01 00:00:01  "ABC"  "DEF"       0       0
2  2020-03-01 00:00:02  "ABC"  "DEF"       7      74
3  2020-03-01 00:00:03  "ABC"  "DEF"       3      10
4  2020-03-01 00:00:04  "ABC"  "DEF"       0       0
5  2020-03-01 00:00:05  "ABC"  "DEF"       0       0
...
n  2020-03-31 23:59:59  "ABC"  "DEF"       0       0

棘手的部分是,var1varN 的列不允许为空并且需要保留,只有 {{1} 的列}} 到 count1 需要得到 null'd。我知道,使用 countN 的偏移量这样做会彻底炸毁我的 DataFrame,但在下一步中,我需要对每个 1S 列进行计算以获得它们的基本统计信息“总和”,“ mean”、“std”、“median”、“var”、“min”、“max”、“分位数”等,这就是为什么我需要所有这些空值 - 所以我的时间序列在全长和我的计算不会被扭曲。

澄清:放大每个组后,我想开始计算每个组的统计数据。为此,我可以想到接下来的两个步骤:(1)将所有放大的组连接回一个巨大的 DataFrame。然后我会再次与 countN 分组并在每个 enlarged_df.groupby([var1, var2]) 列上调用聚合函数 - 或者 - 什么可能更有效,但我想不出如何做到这一点的解决方案现在,(2)也许对已经分组和放大的数据使用类似 .apply 的东西?一些功能是这样的:

countN

我对速度特别感兴趣,关于这个 DataFrame 可以达到的大小。坐这几天了。感谢您的帮助!

1 个答案:

答案 0 :(得分:1)

我的方法是先重新索引组,然后分别填充 var1var2count1count2 中的 nan,然后直接计算各种统计信息.以下是 meanstd 统计信息的示例:

last_day = df.datetime.max()
first_day = df.datetime.min()
idx = pd.date_range(first_day, last_day, freq='s')
                
def apply_function(g):   
    g.index = pd.DatetimeIndex(g.pop('datetime'))
    g = g.reindex(idx, fill_value=np.nan)

    g[['var1', 'var2']] = g[['var1','var2']].fillna(method='ffill').fillna(method='bfill')
    g[['count1', 'count2']] = g[['count1','count2']].fillna(0)

    return pd.Series(dict(
        mean_1 = g.count1.mean(),
        mean_2 = g.count2.mean(),
        std_1 = g.count1.std(),
        std_2 = g.count2.std()))
    
df.groupby(['var1', 'var2']).apply(apply_function)

结果如下:

             mean_1     mean_2     std_1       std_2
var1 var2                                           
A    B     0.333333   4.000000  0.577350    6.928203
ABC  DEF   3.333333  28.000000  3.511885   40.149720
C    C     0.666667  59.666667  1.154701  103.345698
     D     0.333333  24.000000  0.577350   41.569219
     E     1.333333   2.333333  2.309401    4.041452
D    E     0.666667  15.666667  1.154701   27.135463
H    F     0.333333  10.333333  0.577350   17.897858

否则,您首先固定每个组,然后计算统计数据:

gp = df.groupby(['var1', 'var2'])
my_g = gp.get_group(('ABC', 'DEF'))

my_g.index = pd.DatetimeIndex(my_g.pop('datetime'))
my_g = my_g.reindex(idx, fill_value=np.nan)
my_g[['var1', 'var2']] = my_g[['var1','var2']].fillna(method='ffill').fillna(method='bfill')
my_g[['count1', 'count2']] = my_g[['count1','count2']].fillna(0)
print(my_g)

输出:

                    var1 var2  count1  count2
2020-03-01 00:00:01  ABC  DEF     0.0     0.0
2020-03-01 00:00:02  ABC  DEF     7.0    74.0
2020-03-01 00:00:03  ABC  DEF     3.0    10.0
相关问题