【问题标题】:Identifying consecutive NaNs with Pandas用 Pandas 识别连续的 NaN
【发布时间】:2015-05-14 11:52:21
【问题描述】:

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

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

我把它们加起来

Rlength = len(RainD)   # Counts everything, including NaN
Rcount = RainD.count() # Counts only valid numbers
NaN_Number = Rlength - Rcount

如果我的缺失数据多于某个阈值,则丢弃数据集:

Percent_Data = Rlength/100
Five_Percent = Percent_Data*5
if NaN_Number > Five_Percent:
    ...

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

RainD.level = RainD.level.fillna(method='pad', limit=2)

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

documentation for fillna 并没有真正提到当连续的 NaN 多于我指定的 limit=2 时会发生什么,但是当我查看 RainD.describe() 之前和之后的 ...fillna... 并将其与基本 CSV 进行比较时,它是清楚它会填充前两个 NaN,然后​​将其余部分保持原样,而不是出错。

所以,长话短说:

如何使用 Pandas 识别多个连续的 NaN,而不需要一些复杂且耗时的非 Pandas 循环?

【问题讨论】:

    标签: python pandas nan


    【解决方案1】:

    您可以使用多个布尔条件来测试当前值和先前值是否为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
    

    如果您想查找连续的NaNs 出现的位置,您要查找的位置超过 2 个,您可以执行以下操作:

    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
    

    【讨论】:

    • 如何获取这些的索引?
    【解决方案2】:

    如果您希望将其映射回原始索引,或者连续计算 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
    

    例如,

    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
    

    【讨论】:

    • 我正在做类似的事情。如何填补长度为 x 或更短的任何空白?我有 56000 行和 29 列,所以不喜欢手动操作。 Nans数量最少的那一列还有10%!! ======= 抱歉刚刚看到这个:stackoverflow.com/questions/48800345/…,但是它不会向前填充,只会删除它们
    • @AndyThompson - 好问题。在 SO 上可能值得自己提出问题。
    【解决方案3】:

    如果你只想找到连续 NaN 的长度...

    # usual imports
    import pandas as pd
    import numpy as np
    
    # fake data
    data = pd.Series([np.nan,1,1,1,1,1,np.nan,np.nan,np.nan,1,1,np.nan,np.nan])
    
    # code 
    na_groups = data.notna().cumsum()[data.isna()]
    lengths_consecutive_na = na_groups.groupby(na_groups).agg(len)
    longest_na_gap = lengths_consecutive_na.max()
    

    【讨论】:

    • missing_groups ?
    猜你喜欢
    • 2021-04-25
    • 2021-06-05
    • 1970-01-01
    • 2017-09-16
    • 1970-01-01
    • 2018-02-03
    • 1970-01-01
    • 1970-01-01
    • 2023-04-06
    相关资源
    最近更新 更多