Як вибрати рядки з одним або кількома нулями з панд DataFrame без чіткого переліку стовпців?


233

У мене є кадр даних із ~ 300 К рядками та ~ 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]]

Чи є більш елегантний спосіб зробити це (розташування рядків з нулями)?

Відповіді:


384

[Оновлено, щоб адаптувати до сучасного pandas, що має isnullяк методDataFrame ..]

Ви можете використовувати isnullта anyстворювати булеві серії та використовувати їх для індексації у вашому кадрі:

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

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

то коли вам це знадобиться, ви можете набрати:

nans(your_dataframe)

1
df[df.isnull().any(axis=1)]працює, але кидає UserWarning: Boolean Series key will be reindexed to match DataFrame index.. Як можна переписати це більш чітко і таким чином, що не викликає це попередження?
Вішал

3
@vishal Я думаю, що все, що вам потрібно зробити, - це додати loc так, як це; df.loc[df.isnull().any(axis=1)]
Джеймс Дрейпер


0

.any()і .all()чудово підходять для крайніх випадків, але не тоді, коли ви шукаєте певну кількість нульових значень. Ось надзвичайно простий спосіб зробити те, що, на вашу думку, ви просите. Це досить багатослівно, але функціонально.

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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.