Проверка NaN во многих столбцах в Pandas - PullRequest
0 голосов
/ 25 мая 2020

Я хочу добавить двоичный столбец в свой фрейм данных в зависимости от того, содержат ли данные столбцы NaN или нет.

Я пытался сделать это с помощью приведенного ниже кода.

import pandas as pd

dat = pd.DataFrame({'A': [12,34,56,78, 23,None, None], 'B': [90,80,70,23,None, 78, None], 'C': [90,80,70,23,None, 78, None], 'D': [12,34,56,78, 23,None, None]})
dat['A1'] = dat['A'].isnull()
dat['B1'] = dat['B'].isnull()
dat['C1'] = dat['C'].isnull()
dat['ismissing'] = 1 if dat['A1'] == True and dat['B1'] == True and dat['C1'] == True else 0
dat

, но Я получил ValueError в позапрошлой строке.

ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().

Пример ввода:

A     B     C     D
10   NaN    40    NaN
NaN  NaN    80    90
20    45    NaN   89
NaN  NaN    NaN   46

Ожидаемый результат:

A     B     C     D     E
10   NaN    40    NaN   0
NaN  NaN    80    90    0
20    45    NaN   89    0
NaN  NaN    NaN   46    1

Я хочу проверить NaN только для А, Б, C столбцы.

Ответы [ 4 ]

3 голосов
/ 25 мая 2020

IIU C, вы хотите проверить, содержит ли строка со столбцами (A,B,C) все nan или нет.

Вы можете сделать это, используя numpy.where :

In [1711]: import numpy as np

In [1710]: dat['E'] = np.where(dat[['A','B','C']].isnull().all(1), 1, 0)    
In [1711]: dat
Out[1711]: 
      A     B     C     D  E
0  12.0  90.0  90.0  12.0  0
1  34.0  80.0  80.0  34.0  0
2  56.0  70.0  70.0  56.0  0
3  78.0  23.0  23.0  78.0  0
4  23.0   NaN   NaN  23.0  0
5   NaN  78.0  78.0   NaN  0
6   NaN   NaN   NaN   NaN  1

Сравнение производительности:

Ответ Куанг Хоанга:

In [1720]: %timeit df['ismissing'] = df[['A','B','C']].isna().all(axis=1)
989 µs ± 70 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

Ответ YOBEN_S:

In [1719]: %timeit df['New']=~df.index.isin(df.drop('D',1).dropna(thresh=1).index)
2.05 ms ± 113 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

ответ анки:

In [1724]: %timeit df['all_nan'] = df[['A','B','C']].count(axis=1).eq(0).view('i1')
1.48 ms ± 117 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

Мой ответ:

In [1723]: %timeit dat['E'] = np.where(dat[['A','B','C']].isnull().all(1), 1, 0)
914 µs ± 18.5 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

Как видите, мой ответ с np.where самый быстрый.

2 голосов
/ 25 мая 2020

Я создал столбец с истинным и ложным, затем применил один, если он истинный, и 0, если он ложный

dat['ismissing'] = dat.isnull().all(axis=1)
dat['ismissing'] = dat['ismissing'].apply(lambda x: 1 if x else 0)
2 голосов
/ 25 мая 2020

Обратите внимание, что and ожидает единственную логическую переменную, а pd.Series - нет. Вот почему python жалуется, что не знает, как преобразовать pd.Series в логическое значение.

Вместо этого вы можете (и должны) сделать:

df['ismissing'] = df[['A','B','C']].isna().all(axis=1)
1 голос
/ 25 мая 2020

Давайте попробуем что-нибудь новенькое

df['New']=~df.index.isin(df.drop('D',1).dropna(thresh=1).index)
df
      A     B     C     D    New
0  10.0   NaN  40.0   NaN  False
1   NaN   NaN  80.0  90.0  False
2  20.0  45.0   NaN  89.0  False
3   NaN   NaN   NaN  46.0   True
...