计算 pandas DataFrame 中缺失值的行数的最佳方法
Best way to count the number of rows with missing values in a pandas DataFrame
我目前想出了一些解决方法来计算 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'])
我目前拥有的是
a) 对缺失值的细胞进行计数:
>>> sum(df.isnull().values.ravel())
9
b) 对某处有缺失值的行进行计数:
>>> sum([True for idx,row in df.iterrows() if any(row.isnull())])
3
对于第二个计数,我认为只需从 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
所以对于这种大小的 df,我的替代方案要快一些
更新
因此对于具有 80,000 行的 df,我得到以下信息:
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
轻松获胜。
总失踪人数:
df.isnull().sum().sum()
缺少的行:
sum(map(any, df.isnull()))
那numpy.count_nonzero
呢:
np.count_nonzero(df.isnull().values)
np.count_nonzero(df.isnull()) # also works
count_nonzero
很快。但是,我从 (1000,1000) 数组构建了一个数据框,并在不同位置随机插入 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
与 OP 的原始版本相比,时间上没有很大的改进,但代码中的混乱可能更少,您的决定。执行时间实际上没有任何区别
在两个 count_nonzero
方法之间(有和没有 .values
)。
计算行或列中缺失值的简单方法
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)
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
这里有很多错误的答案。 OP 询问具有空值的行数,而不是列数。
这是一个更好的例子:
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(包含 NaN 的列数)的答案。富恩特斯的回答有效。
我是这样得到它的:
df.isnull().any(axis=1).sum()
#4
timeit df.isnull().any(axis=1).sum()
#10000 loops, best of 3: 193 µs per loop
'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
我想如果你只是想看看结果,有一个 pandas func pandas.DataFrame.count.
所以回到这个话题,使用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
关于计算接受的答案中存在缺失值的行数
df.shape[0] - df.dropna().shape[0]
但我宁愿做更直观的(而且我也认为计算速度更快,至少这是我读到的)
len(df) - len(df.dropna())
# 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=1
或axis=0
。如果您想查看 哪些 行包含任何缺失的记录:
>>> df[(df.isna().sum(axis=1) > 0)]
one two three
b NaN NaN NaN
d NaN NaN NaN
g NaN NaN NaN
我目前想出了一些解决方法来计算 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'])
我目前拥有的是
a) 对缺失值的细胞进行计数:
>>> sum(df.isnull().values.ravel())
9
b) 对某处有缺失值的行进行计数:
>>> sum([True for idx,row in df.iterrows() if any(row.isnull())])
3
对于第二个计数,我认为只需从 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
所以对于这种大小的 df,我的替代方案要快一些
更新
因此对于具有 80,000 行的 df,我得到以下信息:
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
轻松获胜。
总失踪人数:
df.isnull().sum().sum()
缺少的行:
sum(map(any, df.isnull()))
那numpy.count_nonzero
呢:
np.count_nonzero(df.isnull().values)
np.count_nonzero(df.isnull()) # also works
count_nonzero
很快。但是,我从 (1000,1000) 数组构建了一个数据框,并在不同位置随机插入 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
与 OP 的原始版本相比,时间上没有很大的改进,但代码中的混乱可能更少,您的决定。执行时间实际上没有任何区别
在两个 count_nonzero
方法之间(有和没有 .values
)。
计算行或列中缺失值的简单方法
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)
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
这里有很多错误的答案。 OP 询问具有空值的行数,而不是列数。
这是一个更好的例子:
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(包含 NaN 的列数)的答案。富恩特斯的回答有效。
我是这样得到它的:
df.isnull().any(axis=1).sum()
#4
timeit df.isnull().any(axis=1).sum()
#10000 loops, best of 3: 193 µs per loop
'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
我想如果你只是想看看结果,有一个 pandas func pandas.DataFrame.count.
所以回到这个话题,使用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
关于计算接受的答案中存在缺失值的行数
df.shape[0] - df.dropna().shape[0]
但我宁愿做更直观的(而且我也认为计算速度更快,至少这是我读到的)
len(df) - len(df.dropna())
# 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=1
或axis=0
。如果您想查看 哪些 行包含任何缺失的记录:
>>> df[(df.isna().sum(axis=1) > 0)]
one two three
b NaN NaN NaN
d NaN NaN NaN
g NaN NaN NaN