用熊猫识别连续的NaN

JC_*_*_CL 8 python nan pandas

我正在阅读一堆CSV文件(水位随时间变化的测量数据),对它们进行各种分析和可视化.

由于我无法控制的各种原因,这些时间序列通常会丢失数据,所以我做了两件事:

我总计算他们

Rlength=len(RainD)   #counts everything, including NaN
Rcount=RainD.count() #counts only valid numbers
NaN_Number=Rlength-Rcount
Run Code Online (Sandbox Code Playgroud)

如果我有比特定阈值更多的缺失数据,则丢弃数据集:

Percent_Data=Rlength/100
Five_Percent=Percent_Data*5
if NaN_Number > Five_Percent:
    ...
Run Code Online (Sandbox Code Playgroud)

如果NaN的数量足够小,我想填补空白

RainD.level=RainD.level.fillna(method='pad',limit=2)
Run Code Online (Sandbox Code Playgroud)

现在问题是:它的月度数据,所以如果我有超过2个连续NaN,我也想丢弃数据,因为这意味着我"猜测"整个赛季,甚至更多.

对文件fillna并没有真正提比我更连续NaN的规定时有发生的事情limit=2,但是当我看到RainD.describe()之前和之后...fillna...,它与基本CSV比较,其明确表示,它填补了前2 NaN的,然后离开休息,而不是错误.

所以,长话短说:

如何用熊猫识别一些连续的NaN,没有一些复杂和耗时的非熊猫循环?

EdC*_*ica 13

您可以使用多个布尔条件来测试当前值和先前值是否为NaN:

In [3]:

df = pd.DataFrame({'a':[1,3,np.NaN, np.NaN, 4, np.NaN, 6,7,8]})
df
Out[3]:
    a
0   1
1   3
2 NaN
3 NaN
4   4
5 NaN
6   6
7   7
8   8
In [6]:

df[(df.a.isnull()) & (df.a.shift().isnull())]
Out[6]:
    a
3 NaN
Run Code Online (Sandbox Code Playgroud)

如果您想查找连续NaNs发生的位置,您可以执行以下操作:

In [38]:

df = pd.DataFrame({'a':[1,2,np.NaN, np.NaN, np.NaN, 6,7,8,9,10,np.NaN,np.NaN,13,14]})
df
Out[38]:
     a
0    1
1    2
2  NaN
3  NaN
4  NaN
5    6
6    7
7    8
8    9
9   10
10 NaN
11 NaN
12  13
13  14

In [41]:

df.a.isnull().astype(int).groupby(df.a.notnull().astype(int).cumsum()).sum()
Out[41]:
a
1    0
2    3
3    0
4    0
5    0
6    0
7    2
8    0
9    0
Name: a, dtype: int32
Run Code Online (Sandbox Code Playgroud)


Lit*_*les 8

如果您希望将其映射回原始索引,或者连续计数 NaN,请使用 Ed 的答案cumsum而不是sum。这对于可视化时间序列中的 NaN 组特别有用:

df = pd.DataFrame({'a':[
    1,2,np.NaN, np.NaN, np.NaN, 6,7,8,9,10,np.NaN,np.NaN,13,14
]})

df.a.isnull().astype(int).groupby(df.a.notnull().astype(int).cumsum()).cumsum()


0     0
1     0
2     1
3     2
4     3
5     0
6     0
7     0
8     0
9     0
10    1
11    2
12    0
13    0
Name: a, dtype: int64
Run Code Online (Sandbox Code Playgroud)

例如,

pd.concat([
        df,
        (
            df.a.isnull().astype(int)
            .groupby(df.a.notnull().astype(int).cumsum())
            .cumsum().to_frame('consec_count')
        )
    ],
    axis=1
)

    a       consec_count
0   1.0     0
1   2.0     0
2   NaN     1
3   NaN     2
4   NaN     3
5   6.0     0
6   7.0     0
7   8.0     0
8   9.0     0
9   10.0    0
10  NaN     1
11  NaN     2
12  13.0    0
13  14.0    0
Run Code Online (Sandbox Code Playgroud)