调用重采样后如何用值0填充na()?

Posted

技术标签:

【中文标题】调用重采样后如何用值0填充na()?【英文标题】:How to fillna() with value 0 after calling resample? 【发布时间】:2017-01-19 23:54:52 【问题描述】:

要么我不理解documentation,要么它已经过时了。

如果我跑了

user[["DOC_ACC_DT", "USER_SIGNON_ID"]].groupby("DOC_ACC_DT").agg(["count"]).resample("1D").fillna(value=0, method="ffill")

得到

TypeError: fillna() got an unexpected keyword argument 'value'

如果我只是跑步

.fillna(0)

我明白了

ValueError: Invalid fill method. Expecting pad (ffill), backfill (bfill) or nearest. Got 0

如果我再设置

.fillna(0, method="ffill") 

我明白了

TypeError: fillna() got multiple values for keyword argument 'method'

所以唯一有效的是

.fillna("ffill")

当然,这只是向前填充。但是,我想用零替换 NaN。我在这里做错了什么?

【问题讨论】:

@AmiTavory 这给了我“ValueError:无效的填充方法。期望填充(ffill),回填(bfill)或最近。得到值='0',方法='ffill'” 代表.fillna("value='0', method='ffill'") 这里有例子。 pandas.pydata.org/pandas-docs/stable/… 几天前我也遇到了同样的问题。看起来 resample().fillna() 仅适用于 method 关键字。你不能传递一个常数。不确定这是一个错误还是设计成那样。文档的正确链接应该是 this 我认为这是一种不同的方法。 @displayname IDK 回答了你的问题,但实际上你不能同时指定一个值和一个方法是有道理的(这意味着什么?)。不过,fillna(0) 的失败令人费解。 @ayhan This 可能会证实你的观点。 【参考方案1】:

好吧,我不明白为什么上面的代码不起作用,我会等待有人给出比这更好的答案,但我刚刚发现

.replace(np.nan, 0)

符合我对.fillna(0) 的期望。

【讨论】:

除非转换 resample 的结果类型,这看起来像是要走的路。 或者你可以使用.asfreq().fillna(0)【参考方案2】:

接近直接使用fillna 的唯一解决方法是在执行.head(len(df.index)) 之后调用它。

我假设 DF.head 在这种情况下很有用,主要是因为当重采样函数应用于 groupby 对象时,它将充当输入的过滤器,由于消除组返回原始形状的缩小.

调用DF.head() 不受此转换的影响,并返回整个DF

演示:

np.random.seed(42)

df = pd.DataFrame(np.random.randn(10, 2),
              index=pd.date_range('1/1/2016', freq='10D', periods=10),
              columns=['A', 'B']).reset_index()

df
       index         A         B
0 2016-01-01  0.496714 -0.138264
1 2016-01-11  0.647689  1.523030
2 2016-01-21 -0.234153 -0.234137
3 2016-01-31  1.579213  0.767435
4 2016-02-10 -0.469474  0.542560
5 2016-02-20 -0.463418 -0.465730
6 2016-03-01  0.241962 -1.913280
7 2016-03-11 -1.724918 -0.562288
8 2016-03-21 -1.012831  0.314247
9 2016-03-31 -0.908024 -1.412304

操作:

resampled_group = df[['index', 'A']].groupby(['index'])['A'].agg('count').resample('2D')
resampled_group.head(len(resampled_group.index)).fillna(0).head(20)

index
2016-01-01    1.0
2016-01-03    0.0
2016-01-05    0.0
2016-01-07    0.0
2016-01-09    0.0
2016-01-11    1.0
2016-01-13    0.0
2016-01-15    0.0
2016-01-17    0.0
2016-01-19    0.0
2016-01-21    1.0
2016-01-23    0.0
2016-01-25    0.0
2016-01-27    0.0
2016-01-29    0.0
2016-01-31    1.0
2016-02-02    0.0
2016-02-04    0.0
2016-02-06    0.0
2016-02-08    0.0
Freq: 2D, Name: A, dtype: float64

【讨论】:

【参考方案3】:

我做了一些测试,很有趣。

示例:

import pandas as pd
import numpy as np

np.random.seed(1)
rng = pd.date_range('1/1/2012', periods=20, freq='S')
df = pd.DataFrame('a':['a'] * 10 + ['b'] * 10,
                   'b':np.random.randint(0, 500, len(rng)), index=rng)
df.b.iloc[3:8] = np.nan
print (df)
                     a      b
2012-01-01 00:00:00  a   37.0
2012-01-01 00:00:01  a  235.0
2012-01-01 00:00:02  a  396.0
2012-01-01 00:00:03  a    NaN
2012-01-01 00:00:04  a    NaN
2012-01-01 00:00:05  a    NaN
2012-01-01 00:00:06  a    NaN
2012-01-01 00:00:07  a    NaN
2012-01-01 00:00:08  a  335.0
2012-01-01 00:00:09  a  448.0
2012-01-01 00:00:10  b  144.0
2012-01-01 00:00:11  b  129.0
2012-01-01 00:00:12  b  460.0
2012-01-01 00:00:13  b   71.0
2012-01-01 00:00:14  b  237.0
2012-01-01 00:00:15  b  390.0
2012-01-01 00:00:16  b  281.0
2012-01-01 00:00:17  b  178.0
2012-01-01 00:00:18  b  276.0
2012-01-01 00:00:19  b  254.0

下采样

Resampler.asfreq 的可能解决方案:

如果使用asfreq,行为与first 的聚合相同:

print (df.groupby('a').resample('2S').first())
                       a      b
a                              
a 2012-01-01 00:00:00  a   37.0
  2012-01-01 00:00:02  a  396.0
  2012-01-01 00:00:04  a    NaN
  2012-01-01 00:00:06  a    NaN
  2012-01-01 00:00:08  a  335.0
b 2012-01-01 00:00:10  b  144.0
  2012-01-01 00:00:12  b  460.0
  2012-01-01 00:00:14  b  237.0
  2012-01-01 00:00:16  b  281.0
  2012-01-01 00:00:18  b  276.0
print (df.groupby('a').resample('2S').first().fillna(0))
                       a      b
a                              
a 2012-01-01 00:00:00  a   37.0
  2012-01-01 00:00:02  a  396.0
  2012-01-01 00:00:04  a    0.0
  2012-01-01 00:00:06  a    0.0
  2012-01-01 00:00:08  a  335.0
b 2012-01-01 00:00:10  b  144.0
  2012-01-01 00:00:12  b  460.0
  2012-01-01 00:00:14  b  237.0
  2012-01-01 00:00:16  b  281.0
  2012-01-01 00:00:18  b  276.0

print (df.groupby('a').resample('2S').asfreq().fillna(0))
                       a      b
a                              
a 2012-01-01 00:00:00  a   37.0
  2012-01-01 00:00:02  a  396.0
  2012-01-01 00:00:04  a    0.0
  2012-01-01 00:00:06  a    0.0
  2012-01-01 00:00:08  a  335.0
b 2012-01-01 00:00:10  b  144.0
  2012-01-01 00:00:12  b  460.0
  2012-01-01 00:00:14  b  237.0
  2012-01-01 00:00:16  b  281.0
  2012-01-01 00:00:18  b  276.0

如果使用replace,另一个值将聚合为mean

print (df.groupby('a').resample('2S').mean())
                           b
a                           
a 2012-01-01 00:00:00  136.0
  2012-01-01 00:00:02  396.0
  2012-01-01 00:00:04    NaN
  2012-01-01 00:00:06    NaN
  2012-01-01 00:00:08  391.5
b 2012-01-01 00:00:10  136.5
  2012-01-01 00:00:12  265.5
  2012-01-01 00:00:14  313.5
  2012-01-01 00:00:16  229.5
  2012-01-01 00:00:18  265.0
print (df.groupby('a').resample('2S').mean().fillna(0))
                           b
a                           
a 2012-01-01 00:00:00  136.0
  2012-01-01 00:00:02  396.0
  2012-01-01 00:00:04    0.0
  2012-01-01 00:00:06    0.0
  2012-01-01 00:00:08  391.5
b 2012-01-01 00:00:10  136.5
  2012-01-01 00:00:12  265.5
  2012-01-01 00:00:14  313.5
  2012-01-01 00:00:16  229.5
  2012-01-01 00:00:18  265.0

print (df.groupby('a').resample('2S').replace(np.nan,0))
                           b
a                           
a 2012-01-01 00:00:00  136.0
  2012-01-01 00:00:02  396.0
  2012-01-01 00:00:04    0.0
  2012-01-01 00:00:06    0.0
  2012-01-01 00:00:08  391.5
b 2012-01-01 00:00:10  136.5
  2012-01-01 00:00:12  265.5
  2012-01-01 00:00:14  313.5
  2012-01-01 00:00:16  229.5
  2012-01-01 00:00:18  265.0

上采样

使用asfreq,与replace相同:

print (df.groupby('a').resample('200L').asfreq().fillna(0))
                           a      b
a                                  
a 2012-01-01 00:00:00.000  a   37.0
  2012-01-01 00:00:00.200  0    0.0
  2012-01-01 00:00:00.400  0    0.0
  2012-01-01 00:00:00.600  0    0.0
  2012-01-01 00:00:00.800  0    0.0
  2012-01-01 00:00:01.000  a  235.0
  2012-01-01 00:00:01.200  0    0.0
  2012-01-01 00:00:01.400  0    0.0
  2012-01-01 00:00:01.600  0    0.0
  2012-01-01 00:00:01.800  0    0.0
  2012-01-01 00:00:02.000  a  396.0
  2012-01-01 00:00:02.200  0    0.0
  2012-01-01 00:00:02.400  0    0.0
  ...

print (df.groupby('a').resample('200L').replace(np.nan,0))
                               b
a                               
a 2012-01-01 00:00:00.000   37.0
  2012-01-01 00:00:00.200    0.0
  2012-01-01 00:00:00.400    0.0
  2012-01-01 00:00:00.600    0.0
  2012-01-01 00:00:00.800    0.0
  2012-01-01 00:00:01.000  235.0
  2012-01-01 00:00:01.200    0.0
  2012-01-01 00:00:01.400    0.0
  2012-01-01 00:00:01.600    0.0
  2012-01-01 00:00:01.800    0.0
  2012-01-01 00:00:02.000  396.0
  2012-01-01 00:00:02.200    0.0
  2012-01-01 00:00:02.400    0.0
  ...
print ((df.groupby('a').resample('200L').replace(np.nan,0).b == 
       df.groupby('a').resample('200L').asfreq().fillna(0).b).all())
True

结论

对于下采样使用相同的聚合函数,例如 sumfirstmean,对于上采样 asfreq

【讨论】:

【参考方案4】:

这里的问题是您尝试从DatetimeIndexResampler 对象调用fillna 方法,该对象由resample 方法返回。如果在 fillna 之前调用聚合函数,它会起作用,例如:df.resample('1H').sum().fillna(0)

【讨论】:

【参考方案5】:

您可以简单地使用sum()。 在https://pandas.pydata.org/docs/reference/api/pandas.core.resample.Resampler.sum.html查看文档

基本上有一个min_count参数,默认为0。也就是说你重采样后,如果count(nan) <= min_count,那么值就是nan。但是因为是0,所以默认是0,所以不需要replace或者fillna。

其实如果你想填充一个非0的值,你可以设置.sum(min_count=1)然后.replace(float('nan'), 'whatever you want')

下面的例子:

import pandas as pd

>>> df = pd.DataFrame('date': pd.date_range('2021-01-01', '2021-01-07', freq='3D'),
                       'value': range(3))
>>> df
        date  value
0 2021-01-01      0
1 2021-01-04      1
2 2021-01-07      2

>>> df.set_index('date').resample('D').sum().reset_index()
        date  value
0 2021-01-01      0
1 2021-01-02      0
2 2021-01-03      0
3 2021-01-04      1
4 2021-01-05      0
5 2021-01-06      0
6 2021-01-07      2

# if you wanna replace nan with some other values, could also use replace() if more than
# 1 column to replace
>>> df.set_index('date').resample('D').sum(min_count=1).fillna(-10).reset_index()
        date  value
0 2021-01-01    0.0
1 2021-01-02  -10.0
2 2021-01-03  -10.0
3 2021-01-04    1.0
4 2021-01-05  -10.0
5 2021-01-06  -10.0
6 2021-01-07    2.0

【讨论】:

以上是关于调用重采样后如何用值0填充na()?的主要内容,如果未能解决你的问题,请参考以下文章

ArcGis重采样

matlab中怎样对数据进行重采样

如何使用音频重采样器对 IF 信号进行重采样

ffmpeg音频重采样

UIButton 中像素精确的 UIImage 重采样

音频压缩编码技术—音频重采样