Sütunları açıkça listelemeden bir panda DataFrame'den bir veya daha fazla null içeren satırlar nasıl seçilir?


235

~ 300K satır ve ~ 40 sütun içeren bir veri çerçevesi var. Herhangi bir satırın null değerler içerip içermediğini öğrenmek ve bu 'null' satırları ayrı bir veri çerçevesine koymak, böylece onları kolayca keşfedebilirim.

Açıkça bir maske oluşturabilirim:

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

Veya şöyle bir şey yapabilirim:

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

Bunu yapmanın daha zarif bir yolu var mı (içinde null olan satırları bulmak)?

Yanıtlar:


387

[ Bir yöntem olarak modern pandas, uyum sağlamak için güncellendi ..]isnullDataFrame

Sen kullanabilirsiniz isnullve anyo kadraja endekse bir boolean Serisi ve kullanımını inşa etmek:

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

[Yaşlılar için pandas:]

İşlevi isnullyöntem yerine kullanabilirsiniz :

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

oldukça kompakt:

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

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

o zaman ihtiyacınız olduğunda şunu yazabilirsiniz:

nans(your_dataframe)

1
df[df.isnull().any(axis=1)]çalışır ama atar UserWarning: Boolean Series key will be reindexed to match DataFrame index.. Bunu nasıl daha açık ve bu uyarı mesajını tetiklemeyecek şekilde yeniden yazar?
Vishal

3
@vishal Tek yapmanız gereken böyle loc eklemek olduğunu düşünüyorum; df.loc[df.isnull().any(axis=1)]
James Draper


0

.any()ve .all()aşırı durumlar için mükemmeldir, ancak belirli sayıda boş değer ararken değil. İşte size sorduğunuza inandığım şeyi yapmanın son derece basit bir yolu. Oldukça ayrıntılı, ama işlevsel.

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

Çıktı

   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]

Eğer benim gibiyseniz ve bu satırları temizlemek istiyorsanız, sadece şunu yazın:

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

Çıktı:

   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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.