Присвоение как fillna(), так и loc(), по-видимому, не работает

Я искал ответ вокруг, но я не могу их найти.

Моя цель: я пытаюсь заполнить некоторые пропущенные значения в DataFrame, используя контролируемое обучение, чтобы решить, как его заполнить.

Мой код выглядит так: ПРИМЕЧАНИЕ. ЭТА ПЕРВАЯ ЧАСТЬ НЕ ВАЖНА, ЭТО ПРОСТО ДЛЯ КОНТЕКСТА

train_df = df[df['my_column'].notna()]     #I need to train the model without using the missing data
train_x = train_df[['lat','long']]         #Lat e Long are the inputs
train_y = train_df[['my_column']]          #My_column is the output
clf = neighbors.KNeighborsClassifier(2)
clf.fit(train_x,train_y)                   #clf is the classifies, here we train it
df_x = df[['lat','long']]                  #I need this part to do the prediction
prediction = clf.predict(df_x)             #clf.predict() returns an array
series_pred = pd.Series(prediction)        #now the array is a series
print(series_pred.shape)                   #RETURNS (2381,)
print(series_pred.isna().sum())            #RETURN 0

Все идет нормально. У меня есть 2381 прогноз (мне нужно всего несколько из них) и внутри нет значения NaN (зачем в прогнозах должно быть значение NaN? Я просто хотел убедиться< /strong>, так как я не понимаю своей ошибки)

Здесь я пытаюсь назначить прогнозы моему кадру данных:

#test_1
df.loc[df['my_colum'].isna(), 'my_colum'] = series_pred  #I assign the predictions using .loc()
#test_2
df['my_colum'] =  df['my_colum'].fillna(series_pred)     #Double check: I assign the predictions using .fillna()
print(df['my_colum'].shape)                      #RETURNS (2381,)
print(df['my_colum'].isna().sum())               #RETURN 6

Как видите, это не сработало: недостающие значения по-прежнему равны 6. Я случайно попробовал немного другой подход:

#test_3
df[['my_colum']] =  df[['my_colum']].fillna(series_pred)     #Will it work?
print(df[['my_colum']].shape)                        #RETURNS (2381, 1)
print(df[['my_colum']].isna().sum())                 #RETURNS 6

Не сработало. Я решил попробовать еще одну вещь: проверить результат fillna еще до назначения результатов исходному df:

In[42]:
print(df['my_colum'].fillna(series_pred).isna().sum())  #extreme test
Out[42]:
6

Итак... где моя очень-очень глупая ошибка? Большое спасибо


РЕДАКТИРОВАТЬ 1

Чтобы показать немного данных,

In[1]:
df.head()
Out[1]:
      my_column      lat    long
 id                                                     
9df   Wil            51     5
4f3   Fabio          47     9
x32   Fabio          47     8   
z6f   Fabio          47     9  
a6f   Giovanni       47     7

Кроме того, я добавил информацию в начале вопроса


person Federico Dorato    schedule 29.01.2020    source источник
comment
привет, Федерико, не могли бы вы опубликовать образец данных, с которыми вы работаете? возможно, и вывод таблицы.   -  person Gorlomi    schedule 29.01.2020
comment
Соответствует ли индекс (индекс строки) series_pred df?   -  person Dan    schedule 29.01.2020
comment
Также не должно быть df.loc[df['my_colum'].isna(), 'my_colum'] = series_pred[df['my_colum'].isna()]? И в чем разница между df и df_x?   -  person Dan    schedule 29.01.2020
comment
@ Дэн Я уверен, что это НЕ совпадает, но элементы должны быть в том же порядке. О разнице между df и df_x я объясню, редактируя вопрос, дайте мне 5 минут   -  person Federico Dorato    schedule 29.01.2020
comment
@Gorlomi Я собираюсь отредактировать вопрос, чтобы ответить тебе, дай мне 5 минут   -  person Federico Dorato    schedule 29.01.2020
comment
Я бы сбросил индекс, чтобы они совпадали... series_pred.index = df.index. Я бы предположил, что что-то вроде fillna соответствует индексу, а не местоположению.   -  person Dan    schedule 29.01.2020
comment
@Dan прав, при использовании Series в fillna он выравнивается по индексу. Если вы уверены в размере ваших данных, то это должен сделать df.loc[df['my_colum'].isna(), 'my_colum'] = prediction, не нужно создавать Series   -  person Ben.T    schedule 29.01.2020
comment
@Ben.T Я сделал то, что вы предложили, и получил ошибку значения. ValueError: несоответствие формы: массив значений формы (2381,) не может быть передан в результат индексации формы (6,). Это имеет смысл, потому что df.loc[df['my_colum'].isna(), 'my_colum'] на самом деле должно состоять только из 6 элементов, а предсказание состоит из 2381 элемента.   -  person Federico Dorato    schedule 29.01.2020
comment
Основываясь на том, что сказали Бен и Дэн, должно быть только два решения: использование fillna() с просьбой игнорировать индекс (вероятно, есть способ) или использование loc() для предсказания только элемента, который я хочу заполнить ( это звучит чище)   -  person Federico Dorato    schedule 29.01.2020
comment
@FedericoDorato, в чем я не уверен, так это в том, почему вы делаете прогноз для всего столбца, в то время как на самом деле вам нужны только 6 строк с Нэн. Итак, как только clf будет обучен, попробуйте df.loc[df['my_colum'].isna(), 'my_colum'] = clf.predict(df.loc[df['my_colum'].isna(), ['lat','long']])   -  person Ben.T    schedule 29.01.2020
comment
@Ben.T Я сделал именно то, что ты сказал, просто написал по-другому. Я предсказываю каждое значение только потому, что для такого рода задач вычисление выполняется очень быстро, и мне нужен был какой-нибудь быстрый код Maccheroni. Пожалуйста, опубликуйте свой ответ ;)   -  person Federico Dorato    schedule 29.01.2020
comment
@FedericoDorato, вы должны принять свой собственный ответ, вы сделали хорошее резюме того, что было сказано в комментариях, мне не нужно добавлять еще один ответ :)   -  person Ben.T    schedule 29.01.2020


Ответы (1)


@Ben.T или @Dan должны опубликовать свои ответы, они заслуживают того, чтобы их признали правильными.

Следуя их намекам, я бы сказал, что есть два решения:

Решение 1 (лучшее): используйте loc()

Проблема

Проблема с текущим решением заключается в том, что df.loc[df['my_column'].isna(), 'my_column'] ожидает получить X значений, где X — количество пропущенных значений. Моя переменная prediction на самом деле имеет как прогноз для отсутствующих значений, так и для неотсутствующих значений.

Решение

pred_df = df[df['my_column'].isna()]        #For the prediction, use a Dataframe with only the missing values. Problem solved
df_x = pred_df[['lat','long']]
prediction = clf.predict(df_x)
df.loc[df['my_column'].isna(), 'my_column'] = prediction

Решение 2. Используйте fillna()

Проблема

Проблема с текущим решением заключается в том, что df['my_colum'].fillna(series_pred) требует, чтобы индексы моего df совпадали с series_pred, что невозможно в этой ситуации, если у вас нет простого индекса в вашем df, например [0, 1, 2, 3, 4. ..]

Решение

Сброс индекса df в самом начале кода.

Почему это не самое лучшее

Самый чистый способ - делать прогноз только тогда, когда он вам нужен. Этот подход легко получить с помощью loc(), и я не знаю, как вы получите его с помощью fillna(), потому что вам нужно будет сохранить индекс через классификацию.

Редактировать: series_pred.index = df['my_column'].isna().index Спасибо, @Dan

person Federico Dorato    schedule 29.01.2020
comment
Это не невозможно, вам просто нужно сделать series_pred.index = df['my_column'].isna().index, а затем fillna все будет в порядке. Но лично я бы также придерживался решения для нарезки. - person Dan; 29.01.2020