Python Pandas如何在不显式列出列的情况下从DataFrame中选择包含一个或多个空值的行?

时间:2013-01-09 22:22:05

标签: python pandas null nan

我有一个〜300K行和~40列的数据帧。 我想知道是否有任何行包含空值 - 并将这些'null'行放入一个单独的数据帧中,以便我可以轻松地探索它们。

我可以明确地创建一个掩码:

mask=False
for col in df.columns: mask = mask | df[col].isnull()
dfnulls = df[mask]

或者我可以这样做:

df.ix[df.index[(df.T == np.nan).sum() > 1]]

是否有一种更优雅的方法(找到包含空值的行)?

6 个答案:

答案 0 :(得分:286)

[已更新以适应现代pandas,其中isnull作为DataFrame的方法..]

您可以使用isnullany构建一个布尔系列,并使用它来索引您的框架:

>>> df = pd.DataFrame([range(3), [0, np.NaN, 0], [0, 0, np.NaN], range(3), range(3)])
>>> df.isnull()
       0      1      2
0  False  False  False
1  False   True  False
2  False  False   True
3  False  False  False
4  False  False  False
>>> df.isnull().any(axis=1)
0    False
1     True
2     True
3    False
4    False
dtype: bool
>>> df[df.isnull().any(axis=1)]
   0   1   2
1  0 NaN   0
2  0   0 NaN

[对于年龄较大的pandas:]

您可以使用函数isnull代替方法:

In [56]: df = pd.DataFrame([range(3), [0, np.NaN, 0], [0, 0, np.NaN], range(3), range(3)])

In [57]: df
Out[57]: 
   0   1   2
0  0   1   2
1  0 NaN   0
2  0   0 NaN
3  0   1   2
4  0   1   2

In [58]: pd.isnull(df)
Out[58]: 
       0      1      2
0  False  False  False
1  False   True  False
2  False  False   True
3  False  False  False
4  False  False  False

In [59]: pd.isnull(df).any(axis=1)
Out[59]: 
0    False
1     True
2     True
3    False
4    False

导致相当紧凑:

In [60]: df[pd.isnull(df).any(axis=1)]
Out[60]: 
   0   1   2
1  0 NaN   0
2  0   0 NaN

答案 1 :(得分:41)

nans = lambda df: df[df.isnull().any(axis=1)]

然后当你需要它时,你可以输入:

nans(your_dataframe)

答案 2 :(得分:2)

.any().all()非常适合极端情况,但当您要查找特定数量的null值时则不然。这是一种我认为您要问的非常简单的方法。它很冗长,但很实用。

import pandas as pd
import numpy as np

# Some test data frame
df = pd.DataFrame({'num_legs':          [2, 4,      np.nan, 0, np.nan],
                   'num_wings':         [2, 0,      np.nan, 0, 9],
                   'num_specimen_seen': [10, np.nan, 1,     8, np.nan]})

# Helper : Gets NaNs for some row
def row_nan_sums(df):
    sums = []
    for row in df.values:
        sum = 0
        for el in row:
            if el != el: # np.nan is never equal to itself. This is "hacky", but complete.
                sum+=1
        sums.append(sum)
    return sums

# Returns a list of indices for rows with k+ NaNs
def query_k_plus_sums(df, k):
    sums = row_nan_sums(df)
    indices = []
    i = 0
    for sum in sums:
        if (sum >= k):
            indices.append(i)
        i += 1
    return indices

# test
print(df)
print(query_k_plus_sums(df, 2))

输出

   num_legs  num_wings  num_specimen_seen
0       2.0        2.0               10.0
1       4.0        0.0                NaN
2       NaN        NaN                1.0
3       0.0        0.0                8.0
4       NaN        9.0                NaN
[2, 4]

然后,如果您像我一样,并且想清除这些行,则只需编写以下内容:

# drop the rows from the data frame
df.drop(query_k_plus_sums(df, 2),inplace=True)
# Reshuffle up data (if you don't do this, the indices won't reset)
df = df.sample(frac=1).reset_index(drop=True)
# print data frame
print(df)

输出:

   num_legs  num_wings  num_specimen_seen
0       4.0        0.0                NaN
1       0.0        0.0                8.0
2       2.0        2.0               10.0

答案 3 :(得分:2)

如果要按一定数量的具有空值的列过滤行,则可以使用以下方法:

    $linkPairs = explode(",", $atts); // separate the pairs
    $output = '';
    $output .= '<li class="slide">
            <p><img src="' . esc_url($atts['image']) . '" alt="" /></p>
            <p>'. $atts['headline'] .'</p>
            <p>'. $atts['body'] .'</p>';
    $li=count($linkPairs);//number of element of array
    $i=1;//track the current location of array_pointer
    foreach($linkPairs as $linkPair) {
        if($i!=$li){
            $symbol="|";//add | if the link is not the last link
        }
        else {
            $symbol="";//add nothing if the link is the last link
        }
        $pair = explode("|", $linkPair); // separate the title and url
        $output .= '<a href="' . $pair[1] . '" target="_blank">' . $pair[0] . '</a>'.$symbol;//$symbol is used to add | to the link
        $i++;
    }
    $output .= '</li>';

所以,这是示例:

您的数据框:

df.iloc[df[(df.isnull().sum(axis=1) >= qty_of_nuls)].index]

如果要选择包含两列或多列具有空值的行,请运行以下命令:

>>> df = pd.DataFrame([range(4), [0, np.NaN, 0, np.NaN], [0, 0, np.NaN, 0], range(4), [np.NaN, 0, np.NaN, np.NaN]])
>>> df
     0    1    2    3
0  0.0  1.0  2.0  3.0
1  0.0  NaN  0.0  NaN
2  0.0  0.0  NaN  0.0
3  0.0  1.0  2.0  3.0
4  NaN  0.0  NaN  NaN

答案 4 :(得分:0)

少四个字符,但多两个毫秒

%%timeit
df.isna().T.any()
# 52.4 ms ± 352 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

%%timeit
df.isna().any(axis=1)
# 50 ms ± 423 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

我可能会使用axis=1

答案 5 :(得分:-1)

df1 = df[df.isna().any(axis=1)]

参考链接:(Display rows with one or more NaN values in pandas dataframe)