df_output.iloc[:, 38:].fillna(0, inplace=True) не срабатывает

На Kaggle пробую применить для очистки NaN и замены их на 0 для диапазона колонов dataframe с помощью:

df_output.iloc[:, 38:].fillna(0, inplace=True)

*38 - это первая колонка, с которой начинается нужный мне диапазон.

Но ничего не происходит:


Ответы (2 шт):

Автор решения: CrazyElf

Вообще должно быть всё нормально, хотя Pandas и выдаёт предупреждение, что возможны глюки из-за того, что вы оперируете копией DataFrame.

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.rand(100000,100))
df.iloc[:,38:] = np.NaN
print(df.isna().sum().sum())
df.iloc[:,38:].fillna(0, inplace=True) # проблемная строка
print(df.isna().sum().sum())

На выходе:

6200000
0
/usr/local/lib/python3.6/dist-packages/pandas/core/frame.py:4153: SettingWithCopyWarning: 
A value is trying to be set on a copy of a slice from a DataFrame

Правильнее делать так:

import pandas as pd
import numpy as np

df = pd.DataFrame(np.random.rand(100000,100))
df.iloc[:,38:] = np.NaN
print(df.isna().sum().sum())
df.iloc[:,38:] = df.iloc[:,38:].fillna(0) # а вот так делать правильно
print(df.isna().sum().sum())

Вывод:

6200000
0

То есть если вы берёте срез от DataFrame, нельзя делать на нём операции inplace, потому что вы оперируете копией данных и может быть потом всякое непонятное.

Надо присваивать новые данные непосредственно в df.loc[] или df.iloc[] явным образом, тогда всё точно будет хорошо.

В будущих версиях Pandas параметр inplace планируют совсем убрать, лучше забудьте про него уже сейчас.

→ Ссылка
Автор решения: Viktor Andriichuk

Я сделал так в Kaggle Notebook:

df.iloc[:,38:] = np.nan_to_num(df.iloc[:,38:], nan=0)
df.iloc[:,38:] = df.iloc[:,38:].astype(int)

И это помогло.

Теперь df.info() выводит нормально:

<class 'pandas.core.frame.DataFrame'> RangeIndex: 50000 entries, 0 to 49999 Columns: 161 entries, Ranking to Yunnan dtypes: float64(2), int64(128), uint8(31) memory usage: 51.1 MB

И можно применить

#MinMax Normalization

from sklearn.preprocessing import MinMaxScaler

scaler = MinMaxScaler()
a = scaler.fit_transform(df)

df = pd.DataFrame(a)
→ Ссылка