Модификация мультииндексных значений DataFrame для Pandas с использованием серии Pandas - PullRequest
1 голос
/ 14 октября 2019

У нас есть многоиндексный DataFrame df

            0  1  2
Name Stock         
Tom  AAPL   0  0  0
     GOOG   0  0  0
     NFLX   0  0  0
John AAPL   0  0  0
     GOOG   0  0  0
     NFLX   0  0  0

и серия s

AAPL    99
NFLX    11
dtype: int64 

Вопрос: Как мы можем установитьзначения в столбце 2 кадра данных df с использованием значений из серии s?

Другими словами, только значения для индекса ('Tom', 'AAPL') и ('Tom', 'NFLX) в кадре данных df должны бытьустановите 99 и 11 соответственно. ('Tom', 'GOOG') должен остаться без изменений.

Неудачная попытка

idx = pd.IndexSlice
df.loc[idx['Tom', :], 2] = s
print(df)
            0  1    2
Name Stock           
Tom  AAPL   0  0  NaN
     GOOG   0  0  NaN
     NFLX   0  0  NaN
John AAPL   0  0  0.0
     GOOG   0  0  0.0
     NFLX   0  0  0.0

Код для воспроизведения проблемы

stocks = ['AAPL', 'GOOG', 'NFLX']
names = ['Tom', 'John']
midx = pd.MultiIndex.from_product([names, stocks], names=['Name','Stock'])
df = pd.DataFrame(index=midx)
for i in range(3):
    df[i] = [0,0,0,0,0,0]
print(df)

s = pd.Series([99, 11], index=['AAPL','NFLX'])
print('\n', s, '\n')

idx = pd.IndexSlice
df.loc[idx['Tom', :], 2] = s
print(df)

Ответы [ 3 ]

2 голосов
/ 14 октября 2019

Создайте MultiIndex в Series с помощью MultiIndex.from_product с Series.reindex для того же индекса, что и у исходного df, а затем установите значения с помощью Series.fillna:

s = pd.Series([99, 11], index=['AAPL','NFLX'])
s.index = pd.MultiIndex.from_product([['Tom'], s.index])
s = s.reindex(df.index)
print(s)
Name  Stock
Tom   AAPL     99.0
      GOOG      NaN
      NFLX     11.0
John  AAPL      NaN
      GOOG      NaN
      NFLX      NaN
dtype: float64

df[2] = s.fillna(df[2])
print(df)
            0  1     2
Name Stock            
Tom  AAPL   0  0  99.0
     GOOG   0  0   0.0
     NFLX   0  0  11.0
John AAPL   0  0   0.0
     GOOG   0  0   0.0
     NFLX   0  0   0.0
1 голос
/ 14 октября 2019

Использование index.get_level_values с loc:

s = pd.Series(data=[99,11], index=['AAPL', 'NFLX'])
s.index = pd.MultiIndex.from_product([['Tom'], s.index]) # thanks Jezrael

idx1 = df.index.get_level_values('Name') == 'Tom'
idx2 = df.index.get_level_values('Stock').isin(s.index)

df.loc[idx1&idx2, 2] = s

Выход

              0    1     2
Name Stock                
Tom  AAPL   0.0  0.0  99.0
     GOOG   0.0  0.0   0.0
     NFLX   0.0  0.0  11.0
John AAPL   0.0  0.0   0.0
     GOOG   0.0  0.0   0.0
     NFLX   0.0  0.0   0.0
0 голосов
/ 14 октября 2019

Вы можете сделать это, установив столбец «Имя» и используя слияние, как показано ниже

df1 = pd.DataFrame([['Tom', 'AAPL', '0', '0', '0'], ['Tom', 'GOOG', '0', '0', '0'], ['Tom', 'NFLX', '0', '0', '0'], ['John', 'AAPL', '0', '0', '0'], ['John', 'GOOG', '0', '0', '0'], ['John', 'NFLX', '0', '0', '0']], columns=('Name', 'Stock', '0', '1', '2'))
df1.set_index(["Name", "Stock"], inplace=True)
df2 = pd.DataFrame([['AAPL', '99'], ['NFLX', '11']], columns=('Stock', 'Value'))

df2["Name"]="Tom"
df1.merge(df2, on=["Name", "Stock"], how="left").set_index(["Name", "Stock"])

Результат

            0  1  2 Value
Name Stock               
Tom  AAPL   0  0  0    99
     GOOG   0  0  0   NaN
     NFLX   0  0  0    11
John AAPL   0  0  0   NaN
     GOOG   0  0  0   NaN
     NFLX   0  0  0   NaN
...