滚动stdev以使用NaN去除异常值

时间:2019-10-15 14:40:40

标签: python pandas dataframe nan rolling-computation

对,所以我对python有点生疏(在4年后将其拉出),并且正在寻找解决此问题的方法。尽管有类似的线程,但我无法弄清楚我在做什么错。

我有一些看起来像这样的数据:

print (fwds)
        1y1yUSD   1y1yEUR    1y1yAUD  1y1yCAD   1y1yCHF   1y1yGBP  \
Date                                                                    
2019-10-15  1.47518 -0.503679   0.681473  1.84996 -0.804212  0.626394   
2019-10-14      NaN -0.513647   0.684232      NaN -0.815201  0.643280   
2019-10-11  1.51515 -0.520474   0.654544  1.84918 -0.812819  0.697584   
2019-10-10  1.39085 -0.538651   0.564055  1.72812 -0.846291  0.546696   
2019-10-09  1.30827 -0.568942   0.564897  1.63652 -0.896871  0.479307   
...             ...       ...        ...      ...       ...       ...   
1995-01-09  8.59473       NaN  10.830200  9.59729       NaN  9.407250   
1995-01-06  8.58316       NaN  10.851200  9.42043       NaN  9.434480   
1995-01-05  8.56470       NaN  10.839000  9.51209       NaN  9.560490   
1995-01-04  8.44306       NaN  10.745900  9.51142       NaN  9.507650   
1995-01-03  8.58847       NaN        NaN  9.38380       NaN  9.611590   

问题在于数据质量不是很好,我需要滚动地除去异常值(因为这些时间序列一直在发展,并且使用静态ZS无效)。

我尝试了一些解决方案。一种是尝试获得滚动的zscore,然后过滤较大的zscore。但是,当我尝试计算zscore时,我的结果是所有NaN:

def zscore(x, window):
    r = x.rolling(window=window)
    m = r.mean().shift(1)
    s = r.std(ddof=0, skipna=True).shift(1)
    z = (x-m)/s
    return z
print (fwds)
print (zscore(fwds, 200))
        1y1yUSD  1y1yEUR  1y1yAUD  1y1yCAD  1y1yCHF  1y1yGBP  1y1yJPY  \
Date                                                                        
2019-10-15      NaN      NaN      NaN      NaN      NaN      NaN      NaN   
2019-10-14      NaN      NaN      NaN      NaN      NaN      NaN      NaN   
2019-10-11      NaN      NaN      NaN      NaN      NaN      NaN      NaN   
2019-10-10      NaN      NaN      NaN      NaN      NaN      NaN      NaN   
2019-10-09      NaN      NaN      NaN      NaN      NaN      NaN      NaN   
...             ...      ...      ...      ...      ...      ...      ...   
1995-01-09      NaN      NaN      NaN      NaN      NaN      NaN      NaN   
1995-01-06      NaN      NaN      NaN      NaN      NaN      NaN      NaN   
1995-01-05      NaN      NaN      NaN      NaN      NaN      NaN      NaN   
1995-01-04      NaN      NaN      NaN      NaN      NaN      NaN      NaN   
1995-01-03      NaN      NaN      NaN      NaN      NaN      NaN      NaN 

另一种方法:

r = fwds.rolling(window=200)
large = r.mean() + 4 * r.std()
small = r.mean() - 4 * r.std()
print(fwds[fwds > mps])
print (fwds[fwds < mps])

返回:

   1y1yUSD  1y1yEUR  1y1yAUD  1y1yCAD  1y1yCHF  1y1yGBP  1y1yJPY  \
Date                                                                        
2019-10-15      NaN      NaN      NaN      NaN      NaN      NaN      NaN   
2019-10-14      NaN      NaN      NaN      NaN      NaN      NaN      NaN   
2019-10-11      NaN      NaN      NaN      NaN      NaN      NaN      NaN   
2019-10-10      NaN      NaN      NaN      NaN      NaN      NaN      NaN   
2019-10-09      NaN      NaN      NaN      NaN      NaN      NaN      NaN   
...             ...      ...      ...      ...      ...      ...      ...   
1995-01-09      NaN      NaN      NaN      NaN      NaN      NaN      NaN   
1995-01-06      NaN      NaN      NaN      NaN      NaN      NaN      NaN   
1995-01-05      NaN      NaN      NaN      NaN      NaN      NaN      NaN   
1995-01-04      NaN      NaN      NaN      NaN      NaN      NaN      NaN   
1995-01-03      NaN      NaN      NaN      NaN      NaN      NaN      NaN 

最大和最小也是如此。在计算滚动stdev或zscores时,有人知道如何处理这些令人毛骨悚然的NaN吗?

任何提示表示赞赏。谢谢!

编辑: 为了进一步明确起见,我希望从图表中删除诸如绿线和棕线中的尖峰之类的东西:

fwds.plot()

下面的链接:https://i.stack.imgur.com/udu5O.png

1 个答案:

答案 0 :(得分:0)

欢迎堆栈溢出...。根据您的用例(以及有多少疯狂的极端值),数据插值应符合要求。...

由于您正在看远期(我认为),所以插值应该在统计上是正确的,除非您的某些缺失值是市场大规模破坏的结果。

您可以使用熊猫的public static final String EMP_GET = "/employee/{employeeId}"; @GetMapping(path = EMP_GET) public EmployeeDto getEmployee(@PathVariable Long employeeId) { return employeeIdService.getTridById(employeeId); } 用内插值填充NaN值。

docs

  

通过线性插值以系列方式填充NaN。

DataFrame.interpolate

编辑我刚刚意识到您正在寻找市场错位,所以您可能不想使用线性插值,因为这会消除丢失数据的影响