Проблемы с назначением значений ячейке Dataframe в пандах - PullRequest
1 голос
/ 04 апреля 2019

Я работаю над объединением различных панд данных и сортировкой индекса окончательного фрейма данных. Я нашел то, что не имеет для меня никакого смысла. Это не дает никакой ошибки, но никакое назначение не происходит. Я приведу упрощенный пример ниже

Дело 1:

import pandas as pd


ind_1 = ['a','a','b','c','c']
df_1 = pd.DataFrame(index=ind_1,columns=['col1','col2'])

df_1.col1.loc['a'].iloc[0] = 1
df_1.col1.loc['b'] = 2
df_1.col1.loc['c'].iloc[0] = 3

print('Original df_1')
print(df_1)

# Original df_1
#   col1 col2
# a    1  NaN
# a  NaN  NaN
# b    2  NaN
# c    3  NaN
# c  NaN  NaN

Вы можете видеть, что это назначение отлично работает. Но давайте создадим фрейм данных из индекса, отсортированного по-разному.

ind_1_sorted = sorted(ind_1,reverse=True)
df_1_sorted = pd.DataFrame(index=ind_1_sorted,columns=['col1','col2'])

df_1_sorted.col1.loc['a'].iloc[0] = 1
df_1_sorted.col1.loc['b'] = 2
df_1_sorted.col1.loc['c'].iloc[0] = 3

print('Sorted df_1')
print(df_1_sorted)

# Sorted df_1
#  col1 col2
# c  NaN  NaN
# c  NaN  NaN
# b    2  NaN
# a  NaN  NaN
# a  NaN  NaN

Теперь вы можете видеть, что назначение работает только для неповторяющегося индекса. Я думал, что проблема должна быть связана с сортировкой, но давайте посмотрим на следующий случай.

Случай 2:

ind_2 = ['c','c','b','a','a']
df_2 = pd.DataFrame(index=ind_2,columns=['col1','col2'])

df_2.col1.loc['a'].iloc[0] = 1
df_2.col1.loc['b'] = 2
df_2.col1.loc['c'].iloc[0] = 3

print('Original df_2')
print(df_2)

# Original df_2
#  col1 col2
# c  NaN  NaN
# c  NaN  NaN
# b    2  NaN
# a  NaN  NaN
# a  NaN  NaN

Теперь мы не получаем назначения без осуществления сортировки. Посмотрим, что произойдет, если я отсортирую индекс

ind_2_sorted = sorted(ind_2,reverse=False)
df_2_sorted = pd.DataFrame(index=ind_2_sorted,columns=['col1','col2'])

df_2_sorted.col1.loc['a'].iloc[0] = 1
df_2_sorted.col1.loc['b'] = 2
df_2_sorted.col1.loc['c'].iloc[0] = 3

print('Sorted df_2')
print(df_2_sorted)

# Sorted df_2
#   col1 col2
# a    1  NaN
# a  NaN  NaN
# b    2  NaN
# c    3  NaN
# c  NaN  NaN

А теперь назначение работает после сортировки !! Единственное отличие, которое я вижу, состоит в том, что назначение работает, когда индекс сортируется «стандартным способом» (в данном случае в алфавитном порядке). Имеет ли это какой-либо смысл?

Если решение использует сначала индекс, отсортированный по алфавиту, а затем отсортировать его в нужном мне порядке, как я могу выполнить эту сортировку, используя повторяющиеся индексы, как в этих примерах?

Спасибо!

1 Ответ

2 голосов
/ 04 апреля 2019

Как отметил пользователь Quickbeam2k1, проблема связана с назначением цепочки.

Индексные объекты имеют метод, называемый get_loc, который можно использовать для преобразования меток в позиции, однако его тип возвращаемого значения является полиморфным, и поэтому я предпочитаю не использовать его.

Используя np.nonzero и фильтрацию по индексу и столбцу информационного кадра, мы можем преобразовать метки в позиционные ссылки и изменить информационный кадр, используя iloc вместо loc

т.е.. Ваш первый пример кода может быть переписан как:

# original
df_1.col1.loc['a'].iloc[0] = 1
df_1.col1.loc['b'] = 2
df_1.col1.loc['c'].iloc[0] = 3

# works for all indices
col1_mask = df_1.columns == 'col1'
a_mask, = np.nonzero(df_1.index == 'a')
b_mask, = np.nonzero(df_1.index == 'b')
c_mask, = np.nonzero(df_1.index == 'c')
df_1.iloc[a_mask[0], col1_mask] = 1
df_1.iloc[b_mask, col1_mask] = 1
df_1.iloc[c_mask[0], col1_mask] = 3

Аналогично для других примеров

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...