在pandas DataFrame中计算缺失值行数的最佳方法

44

我目前想到了一些方法来计算Pandas DataFrame 中缺失值的数量。它们相当丑陋,我想知道是否有更好的方法。

让我们创建一个示例DataFrame

from numpy.random import randn
df = pd.DataFrame(randn(5, 3), index=['a', 'c', 'e', 'f', 'h'],
               columns=['one', 'two', 'three'])
df = df.reindex(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'])

enter image description here

我目前拥有的是:

a) 统计缺失值的单元格:

>>> sum(df.isnull().values.ravel())
9

b) 统计具有缺失值的行数:

>>> sum([True for idx,row in df.iterrows() if any(row.isnull())])
3

3
统计具有缺失值的行数:len(df) - len(df.dropna()) - NeStack
9个回答

47

对于第二种情况,我认为只需要从dropna返回的行数中减去缺失值所在行的数量:


Translated:

对于第二种情况,我认为只需要从dropna返回的行数中减去缺失值所在行的数量:

In [14]:

from numpy.random import randn
df = pd.DataFrame(randn(5, 3), index=['a', 'c', 'e', 'f', 'h'],
               columns=['one', 'two', 'three'])
df = df.reindex(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'])
df
Out[14]:
        one       two     three
a -0.209453 -0.881878  3.146375
b       NaN       NaN       NaN
c  0.049383 -0.698410 -0.482013
d       NaN       NaN       NaN
e -0.140198 -1.285411  0.547451
f -0.219877  0.022055 -2.116037
g       NaN       NaN       NaN
h -0.224695 -0.025628 -0.703680
In [18]:

df.shape[0] - df.dropna().shape[0]
Out[18]:
3

可以使用内置方法来实现第一个目标:

In [30]:

df.isnull().values.ravel().sum()
Out[30]:
9

时间安排

In [34]:

%timeit sum([True for idx,row in df.iterrows() if any(row.isnull())])
%timeit df.shape[0] - df.dropna().shape[0]
%timeit sum(map(any, df.apply(pd.isnull)))
1000 loops, best of 3: 1.55 ms per loop
1000 loops, best of 3: 1.11 ms per loop
1000 loops, best of 3: 1.82 ms per loop
In [33]:

%timeit sum(df.isnull().values.ravel())
%timeit df.isnull().values.ravel().sum()
%timeit df.isnull().sum().sum()
1000 loops, best of 3: 215 µs per loop
1000 loops, best of 3: 210 µs per loop
1000 loops, best of 3: 605 µs per loop

所以对于这个大小的数据框,我的替代方法会稍微快一些。

更新

所以对于一个有80000行的数据框,我得到了以下结果:

In [39]:

%timeit sum([True for idx,row in df.iterrows() if any(row.isnull())])
%timeit df.shape[0] - df.dropna().shape[0]
%timeit sum(map(any, df.apply(pd.isnull)))
%timeit np.count_nonzero(df.isnull())
1 loops, best of 3: 9.33 s per loop
100 loops, best of 3: 6.61 ms per loop
100 loops, best of 3: 3.84 ms per loop
1000 loops, best of 3: 395 µs per loop
In [40]:

%timeit sum(df.isnull().values.ravel())
%timeit df.isnull().values.ravel().sum()
%timeit df.isnull().sum().sum()
%timeit np.count_nonzero(df.isnull().values.ravel())
1000 loops, best of 3: 675 µs per loop
1000 loops, best of 3: 679 µs per loop
100 loops, best of 3: 6.56 ms per loop
1000 loops, best of 3: 368 µs per loop

事实上,np.count_nonzero 轻松胜出。


1
我认为你对于计算有缺失值的行数的回答可以去掉 shape,只需要执行 len(df) - len(df.dropna()) 即可。 - NeStack

17
很多答案都是错误的,OP要求的是具有null值的行数,而不是列数。
以下是一个更好的示例:
from numpy.random import randn
df = pd.DataFrame(randn(5, 3), index=['a', 'c', 'e', 'f', 'h'],columns=['one','two', 'three'])
df = df.reindex(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h','asdf'])
print(df)

现在很明显有4行具有空值。

           one       two     three
a    -0.571617  0.952227  0.030825
b          NaN       NaN       NaN
c     0.627611 -0.462141  1.047515
d          NaN       NaN       NaN
e     0.043763  1.351700  1.480442
f     0.630803  0.931862  1.500602
g          NaN       NaN       NaN
h     0.729103 -1.198237 -0.207602
asdf       NaN       NaN       NaN

如果你使用这里的某些答案,你将得到3作为答案(即缺失值的列数)。Fuentes的答案可行。

以下是我得出答案的方法:

df.isnull().any(axis=1).sum()
#4
timeit df.isnull().any(axis=1).sum()
#10000 loops, best of 3: 193 µs per loop

'Fuentes':


(翻译:'Fuentes')
sum(df.apply(lambda x: sum(x.isnull().values), axis = 1)>0)
#4
timeit sum(df.apply(lambda x: sum(x.isnull().values), axis = 1)>0)
#1000 loops, best of 3: 677 µs per loop

12

那么 numpy.count_nonzero 呢:

 np.count_nonzero(df.isnull().values)   
 np.count_nonzero(df.isnull())           # also works  

count_nonzero非常快速。然而,我从一个(1000,1000)的数组构建了一个数据帧,并在不同的位置随机插入了100个NaN值,并在iPython中测量了各种答案的时间:

count_nonzero很快,但我使用一个(1000,1000)的数组构建了一个DataFrame,并在随机位置插入了100个NaN值,然后在iPython中测量了各种答案的时间:

%timeit np.count_nonzero(df.isnull().values)
1000 loops, best of 3: 1.89 ms per loop

%timeit df.isnull().values.ravel().sum()
100 loops, best of 3: 3.15 ms per loop

%timeit df.isnull().sum().sum()
100 loops, best of 3: 15.7 ms per loop

虽然与原始帖子相比没有太大的时间改进,但在代码方面可能不那么令人困惑,这取决于你。两种count_nonzero方法(有和没有.values)在执行时间上实际上并没有任何区别。


方便起见,以下是文档链接:https://docs.scipy.org/doc/numpy/reference/generated/numpy.count_nonzero.html - Cole Murray

11

计算缺失值的简单方法,可以针对行或列进行计数。

df.apply(lambda x: sum(x.isnull().values), axis = 0) # For columns
df.apply(lambda x: sum(x.isnull().values), axis = 1) # For rows

至少有一个缺失值的行数:

sum(df.apply(lambda x: sum(x.isnull().values), axis = 1)>0)

5

总缺失:

df.isnull().sum().sum()

缺失行:

sum(map(any, df.isnull()))

1
# TOTAL number of missing values:
>>> df.isna().sum().sum()
9

# number of ROWS with at least one missing value:
>>> (df.isna().sum(axis=1) > 0).sum()
3

# number of COLUMNS with at least one missing value:
>>> (df.isna().sum(axis=0) > 0).sum()
3

在这个例子中,缺失值的行数和列数相同,但不要让这使你困惑。重点是在第一个sum()方法中使用axis=1axis=0。如果你想查看哪些行包含任何缺失记录:
>>> df[(df.isna().sum(axis=1) > 0)]

one two three
b   NaN NaN NaN
d   NaN NaN NaN
g   NaN NaN NaN

0

我认为如果你只是想查看结果,有一个名为pandas.DataFrame.count的pandas函数。

因此回到这个主题,使用df.count(axis=1),你会得到如下结果:

a    3
b    0
c    3
d    0
e    3
f    3
g    0
h    3
dtype: int64

它将告诉您每行中有多少个非NaN参数。同时, -(df.count(axis=1) - df.shape[1]) 表示

a    0
b    3
c    0
d    3
e    0
f    0
g    3
h    0
dtype: int64

0

sum(df.count(axis=1) < len(df.columns)),返回行数少于非空列数的行数。

例如,以下数据框有两行缺失值。

>>> df = pd.DataFrame({"a":[1, None, 3], "b":[4, 5, None]})
>>> df
    a   b
0   1   4
1 NaN   5
2   3 NaN
>>> df.count(axis=1)
0    2
1    1
2    1
dtype: int64
>>> df.count(axis=1) < len(df.columns)
0    False
1     True
2     True
dtype: bool
>>> sum(df.count(axis=1) < len(df.columns))
2

0

关于计算具有某些缺失值的行数,接受的答案提供了以下内容

df.shape[0] - df.dropna().shape[0]

但我更倾向于做更直观的方法(我也认为这样计算速度更快,至少这是我所读到的)

len(df) - len(df.dropna())

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接