df_output.iloc[:, 38:].fillna(0, inplace=True) не срабатывает
На Kaggle пробую применить для очистки NaN и замены их на 0 для диапазона колонов dataframe с помощью:
df_output.iloc[:, 38:].fillna(0, inplace=True)
*38 - это первая колонка, с которой начинается нужный мне диапазон.
Но ничего не происходит:
Ответы (2 шт):
Вообще должно быть всё нормально, хотя 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 планируют совсем убрать, лучше забудьте про него уже сейчас.
Я сделал так в 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)
