在Pandas Dataframe中计算NaN,但忽略领先者

时间:2019-08-16 06:09:21

标签: python pandas

我想对数据框中包含的每列的NaN进行计数,但是要忽略开头的NaN。

所以我的数据框具有以下结构:

import pandas as pd
import numpy as np
df=pd.DataFrame({'Date': 
pd.date_range(pd.datetime.today().strftime("%m/%d/%Y"),periods=10).tolist(),
             'Col1': [np.nan,np.nan,np.nan,4,5,6,7,np.nan,np.nan,np.nan],
             'Col2': [np.nan,np.nan,np.nan,4,5,6,7,8,9,np.nan],  
             'Col3': [np.nan,2,3,4,np.nan,6,7,8,9,np.nan] })
df
        Date  Col1  Col2  Col3
0 2019-08-16   NaN   NaN   NaN
1 2019-08-17   NaN   NaN   2.0
2 2019-08-18   NaN   NaN   3.0
3 2019-08-19   4.0   4.0   4.0
4 2019-08-20   5.0   5.0   NaN
5 2019-08-21   6.0   6.0   6.0
6 2019-08-22   7.0   7.0   7.0
7 2019-08-23   NaN   8.0   8.0
8 2019-08-24   NaN   9.0   9.0
9 2019-08-25   NaN   NaN   NaN

所需的输出应该是一个数据帧,某物。喜欢:

Col1  Col2  Col3
  3     1     2

3 个答案:

答案 0 :(得分:1)

首先不带DataFrame.iloc过滤所有列,然后用DataFrame.countNaN s减少带有误配值的非nans值,并计算所有非nans值:

df1 = df.iloc[:, 1:]
a =  df1.ffill().count() - df1.count()

或者:

df1 = df.iloc[:, 1:]
a = df1.isna().sum() - df1.ffill().isna().sum()

或者:

df1 = df.iloc[:, 1:]
a = df1.mask(df1.ffill().isna(), 1).isna().sum()

print (a)

Col1    3
Col2    1
Col3    2
dtype: int64

最后一次是否需要一行DataFrame:

df1 = a.to_frame(0).T
print (df1)
   Col1  Col2  Col3
0     3     1     2

答案 1 :(得分:1)

您的df示例与您的输出示例不匹配。

设置:

df=pd.DataFrame({'Date': 
pd.date_range(pd.datetime.today().strftime("%m/%d/%Y"),periods=10).tolist(),
             'Col1': [np.nan,np.nan ,np.nan,4,5,6,7,np.nan,np.nan,np.nan],
             'Col2': [np.nan,np.nan,np.nan,4,5,6,7,8,9,np.nan],  
             'Col3': [np.nan,2,3,4,np.nan,6,7,8,9,np.nan] })

解决方案:

df.iloc[:,1:].apply(lambda x: x.iloc[x.notna().idxmax():].isna().sum())
Col1    3
Col2    1
Col3    2
dtype: int64

正如@jezrael所指出的,如果列中的所有值均为nan,则此解决方案可能无法正常工作。

Jezrael的解决方案更加优雅。请用他的。

答案 2 :(得分:1)

一种解决方案是使用label中的scipy.ndimage函数来查找nan的所有连续补丁,然后对标签超过1的条目进行计数。

from scipy.ndimage import label
res = df.isnull().apply(lambda s: (label(s)[0] > 1).sum())
# Date    0
# Col1    3
# Col2    1
# Col3    2