Как последовательно заменить выбранные строки фрейма данных pandas массивом np?

У меня есть фреймворк pandas

     A  B  C
0  NaN  2  6
1  3.0  4  0
2  NaN  0  4
3  NaN  1  2

где у меня есть столбец A, который имеет значения NaN в некоторых строках (не обязательно подряд).

Я хочу заменить эти значения нет постоянным значением (что делает pd.fillna), а скорее значениями из массива numpy.

Итак, желаемый результат:

     A  B  C
0  1.0  2  6
1  3.0  4  0
2  5.0  0  4
3  7.0  1  2

Я не уверен, что метод .replace поможет и здесь, поскольку он, похоже, заменяет value <-> value через словарь. В то время как здесь я хочу последовательно изменить NaN на соответствующее ему значение (по индексу) в массиве np.

Я пытался:

MWE:

huh = pd.DataFrame([[np.nan, 2, 6],
                    [3, 4, 0],
                    [np.nan, 0, 4],
                    [np.nan, 1, 2]],
                   columns=list('ABC'))

huh.A[huh.A.isnull()] = np.array([1,5,7])  # what i want to do, but this gives error

дает ошибку

SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy '''

Я прочитал документацию, но не могу понять, как это сделать с .loc. Как мне сделать это правильно, желательно без цикла for?

Дополнительная информация:

  • Количество элементов в массиве np всегда будет соответствовать количеству NaN в кадре данных, поэтому в вашем ответе нет необходимости проверять это.
2
0
849
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Вы действительно близки, нужен DataFrame.loc, чтобы избежать связанные задания:

huh.loc[huh.A.isnull(), 'A'] = np.array([1,5,7])
print (huh)
     A  B  C
0  1.0  2  6
1  3.0  4  0
2  5.0  0  4
3  7.0  1  2

что происходит при несовпадении длины i.2 when array has more than 3 values или huh['A'] has more NaN than assigning array

pyd 10.09.2018 07:24

Это не проблема, уведомление OP The number of elements in the np array will always match the number of NaN in the dataframe, so your answer does not need to check for this.

jezrael 10.09.2018 07:25

да, получаю ValueError: shape mismatch: value array of shape (4,) could not be broadcast to indexing result of shape (3,) при несовпадении длин

pyd 10.09.2018 07:27

@pyd - я думаю, что нужно проверить длину, нужно время для решения.

jezrael 10.09.2018 07:28

это так странно, это работает с моим минимальным примером, но когда я реализую его в своем реальном коде, я все равно получаю SettingwithcopyWarning. (с использованием .loc) Тем не менее, nan в основном фрейме данных "да" все равно будет заменен ... Итак, я получил желаемый результат, но предупреждение все еще отображается .. Мне нужно время, чтобы отладить это .. но спасибо за тем не менее быстрый ответ.

user10340206 10.09.2018 07:50

@QuestionAsker - Думаю, тоже должна быть другая проблема, проверьте, не обязательно ли копировать

jezrael 10.09.2018 07:52

@jezrael Вы были правы, мне нужен был .copy(). Спасибо!

user10340206 10.09.2018 15:19

zip

Это должно учитывать неравномерную длину

m = huh.A.isna()
a = np.array([1, 5, 7])
s = pd.Series(dict(zip(huh.index[m], a)))

huh.fillna({'A': s})

     A  B  C
0  1.0  2  6
1  3.0  4  0
2  5.0  0  4
3  7.0  1  2

Другие вопросы по теме