【问题标题】:Resample time series excluding nan data重新采样不包括 nan 数据的时间序列
【发布时间】:2014-10-27 10:01:41
【问题描述】:

我有一个每日数据时间序列,其中有许多 NaN 值。我想重新采样月度数据,仅考虑 NaN 值少于 10 天的月份。

我尝试过使用 resample 函数,通过这种方式:

df = 
Date          Sr_1    Sr_2    Sr_3
01/12/1978    32.2    20.8    NaN
02/12/1978    32.2    20.6    NaN
03/12/1978    31.6    22      NaN
04/12/1978    28.2    19.4    NaN
05/12/1978    29.8    22.8    24.6
06/12/1978    32      22.2    25.8
07/12/1978    32.8    23.2    NaN
08/12/1978    29.8    NaN     26.8
09/12/1978    31.4    21.4    25.4
10/12/1978    28.8    24      NaN
11/12/1978    30.8    20      NaN
12/12/1978    32      24      25.6
13/12/1978    33      23.2    25.8
14/12/1978    32.4    22.4    24.6
15/12/1978    30      20.6    NaN
16/12/1978    32.6    21.2    NaN
17/12/1978    33      23.4    NaN
18/12/1978    30.4    20.4    26.4
19/12/1978    32      22.2    NaN
20/12/1978    32.2    NaN     NaN
21/12/1978    32.8    22.8    NaN
22/12/1978    32      22.2    NaN
23/12/1978    32.2    NaN     NaN
24/12/1978    31.4    NaN     NaN
25/12/1978    33      NaN     25.6
26/12/1978    33.4    20.6    NaN
27/12/1978    33.6    22.2    NaN
28/12/1978    33.6    23.4    NaN
29/12/1978    33.8    23.4    NaN
30/12/1978    33.2    NaN     25.2
31/12/1978    33.6    23.4    25.2
df.resample('1MS', how='mean')

结果是:

01/12/1978    31.9    22.1    25.5

但是 Sr_3 有超过 10 个 NaN 值,所以结果一定是 NaN。

谢谢

【问题讨论】:

    标签: pandas resampling


    【解决方案1】:

    这是一种老套的方式。首先计算 NaN 的数量,然后使用 where 将这些 NaN 取出。

    In [11]: g = df1.groupby(pd.TimeGrouper('1MS'))
    

    注意:使用isnullsum 计数。

    In [12]: g.apply(lambda x: pd.isnull(x).sum()).unstack(1)  # Note: columns match res
    Out[12]:
                Sr_1  Sr_2  Sr_3
    Date
    1978-01-01     0     0     1
    1978-02-01     0     0     1
    1978-03-01     0     0     1
    1978-04-01     0     0     1
    1978-05-01     0     0     0
    1978-06-01     0     0     0
    1978-07-01     0     0     1
    1978-08-01     0     1     0
    1978-09-01     0     0     0
    1978-10-01     0     0     1
    1978-11-01     0     0     1
    1978-12-01     0     5    13
    
    In [13]: under_ten_nan = g.apply(lambda x: pd.isnull(x).sum()).unstack(1) <= 10
    

    使用 where 将超过 10 的条目设为 NaN:

    In [14]: res.where(under_ten_nan)
    Out[14]:
                 Sr_1   Sr_2  Sr_3
    Date
    1978-01-01  32.20  20.80   NaN
    1978-02-01  32.20  20.60   NaN
    1978-03-01  31.60  22.00   NaN
    1978-04-01  28.20  19.40   NaN
    1978-05-01  29.80  22.80  24.6
    1978-06-01  32.00  22.20  25.8
    1978-07-01  32.80  23.20   NaN
    1978-08-01  29.80    NaN  26.8
    1978-09-01  31.40  21.40  25.4
    1978-10-01  28.80  24.00   NaN
    1978-11-01  30.80  20.00   NaN
    1978-12-01  32.51  22.36   NaN
    

    【讨论】:

    • 谢谢,凭直觉我就这样走了。
    【解决方案2】:

    您可以预先过滤组(使用与@Andy Hayden 类似的算法)。不知道这是否不那么 hacky!

    这是 0.14.0 中的新功能(您可以 pd.TimeGrouper('1MS') 在以前的版本中

    In [20]: g = pd.Grouper(freq='1MS')
    

    过滤并仅保留列满足具有 groupby(g).mean() 所做的)

    In [28]: pd.concat([ 
                        df.groupby(g)[c].filter(lambda x: x.isnull().sum()<10).groupby(g).mean() 
                        for c in df.columns ],axis=1)
    
    Out[28]: 
                 Sr_1   Sr_2  Sr_3
    Date                          
    1978-01-01  32.20  20.80   NaN
    1978-02-01  32.20  20.60   NaN
    1978-03-01  31.60  22.00   NaN
    1978-04-01  28.20  19.40   NaN
    1978-05-01  29.80  22.80  24.6
    1978-06-01  32.00  22.20  25.8
    1978-07-01  32.80  23.20   NaN
    1978-08-01  29.80    NaN  26.8
    1978-09-01  31.40  21.40  25.4
    1978-10-01  28.80  24.00   NaN
    1978-11-01  30.80  20.00   NaN
    1978-12-01  32.51  22.36   NaN
    

    这必须逐列完成,然后进行连接,因为过滤器适用于整个组。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-12-15
      • 1970-01-01
      • 2020-12-28
      • 1970-01-01
      • 1970-01-01
      • 2019-01-18
      • 1970-01-01
      • 2021-12-31
      相关资源
      最近更新 更多