¿Cómo seleccionar filas con uno o más nulos de un DataFrame de pandas sin enumerar columnas explícitamente?


234

Tengo un marco de datos con ~ 300K filas y ~ 40 columnas. Quiero averiguar si alguna fila contiene valores nulos, y colocar estas filas 'nulas' en un marco de datos separado para poder explorarlas fácilmente.

Puedo crear una máscara explícitamente:

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

O puedo hacer algo como:

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

¿Hay una forma más elegante de hacerlo (ubicando filas con valores nulos)?

Respuestas:


384

[Actualizado para adaptarse a lo moderno pandas, que tiene isnullcomo método deDataFrame s ..]

Puede usar isnully anypara construir una Serie booleana y usar eso para indexar en su marco:

>>> 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

[Para mayores pandas :]

Puede usar la función en isnulllugar del método:

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

que conduce a lo bastante compacto:

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

75
def nans(df): return df[df.isnull().any(axis=1)]

entonces, cuando lo necesite, puede escribir:

nans(your_dataframe)

1
df[df.isnull().any(axis=1)]funciona pero tira UserWarning: Boolean Series key will be reindexed to match DataFrame index.. ¿Cómo se reescribe esto más explícitamente y de una manera que no active ese mensaje de advertencia?
Vishal

3
@vishal Creo que todo lo que necesita hacer es agregar loc como este; df.loc[df.isnull().any(axis=1)]
James Draper


0

.any()y .all()son excelentes para los casos extremos, pero no cuando buscas un número específico de valores nulos. Aquí hay una manera extremadamente simple de hacer lo que creo que estás pidiendo. Es bastante detallado, pero funcional.

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))

Salida

   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]

Entonces, si eres como yo y quieres borrar esas filas, solo escribe esto:

# 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)

Salida:

   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
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.