Отбрасывает столбец, если он превышает определенное количество значений NA
Я хочу написать программу, которая удаляет столбец, если он превышает определенное количество значений NA. Это то, что я сделал.
def check(x):
for column in df:
if df.column.isnull().sum() > 2:
df.drop(column,axis=1)
нет ошибки при выполнении вышеуказанного кода, но при выполнении df.apply(check)
Есть куча ошибок.
PS: я знаю о аргументе молотить в df.dropna(thresh,axis)
Любые советы? Почему мой код не работает?
Спасибо
3 ответа
Я думаю, что лучше всего здесь использовать dropna
с параметром thresh
:
thresh: int, необязательный
Требуйте, чтобы многие не-NA значения.
Поэтому для векторизации решения вычтите его из длины DataFrame
:
N = 2
df = df.dropna(thresh=len(df)-N, axis=1)
print (df)
A D E F
0 a 1 5.0 a
1 b 3 3.0 a
2 c 5 6.0 a
3 d 7 9.0 b
4 e 1 2.0 b
5 f 0 NaN b
Я предлагаю использовать DataFrame.pipe
для применения функции для ввода DataFrame
с изменением df.column
в df[column]
, потому что точечная нотация с динамическими именами столбцов из переменной не удалась (попробуйте выбрать имя столбца column
):
df = pd.DataFrame({'A':list('abcdef'),
'B':[np.nan,np.nan,np.nan,5,5,np.nan],
'C':[np.nan,8,np.nan,np.nan,2,3],
'D':[1,3,5,7,1,0],
'E':[5,3,6,9,2,np.nan],
'F':list('aaabbb')})
print (df)
A B C D E F
0 a NaN NaN 1 5.0 a
1 b NaN 8.0 3 3.0 a
2 c NaN NaN 5 6.0 a
3 d 5.0 NaN 7 9.0 b
4 e 5.0 2.0 1 2.0 b
5 f NaN 3.0 0 NaN b
def check(df):
for column in df:
if df[column].isnull().sum() > 2:
df.drop(column,axis=1, inplace=True)
return df
print (df.pipe(check))
A D E F
0 a 1 5.0 a
1 b 3 3.0 a
2 c 5 6.0 a
3 d 7 9.0 b
4 e 1 2.0 b
5 f 0 NaN b
Хотя ответ Джезраэль работает, это не тот подход, который вы должны делать. Вместо этого создайте маску: ~df.isnull().sum().gt(2)
и применить его с .loc[:,m]
чтобы получить доступ к столбцам.
Полный пример:
import pandas as pd
import numpy as np
df = pd.DataFrame({
'A':list('abcdef'),
'B':[np.nan,np.nan,np.nan,5,5,np.nan],
'C':[np.nan,8,np.nan,np.nan,2,3],
'D':[1,3,5,7,1,0],
'E':[5,3,6,9,2,np.nan],
'F':list('aaabbb')
})
m = ~df.isnull().sum().gt(2)
df = df.loc[:,m]
print(df)
Возвращает:
A D E F
0 a 1 5.0 a
1 b 3 3.0 a
2 c 5 6.0 a
3 d 7 9.0 b
4 e 1 2.0 b
5 f 0 NaN b
объяснение
Предположим, мы распечатываем столбцы и маску перед ее применением.
print(df.columns.tolist())
print(m.tolist())
Это вернуло бы это:
['A', 'B', 'C', 'D', 'E', 'F']
[True, False, False, True, True, True]
Столбцы B и C являются нежелательными (False). Они удаляются при наложении маски.
Кроме того, вы можете использовать count
который считает ненулевые значения
In [23]: df.loc[:, df.count().gt(len(df.index) - 2)]
Out[23]:
A D E F
0 a 1 5.0 a
1 b 3 3.0 a
2 c 5 6.0 a
3 d 7 9.0 b
4 e 1 2.0 b
5 f 0 NaN b