【问题标题】:Modify Pandas Multi-Index DataFrame Values using Pandas Series使用 Pandas 系列修改 Pandas 多索引 DataFrame 值
【发布时间】:2019-10-14 09:03:14
【问题描述】:

我们有一个多索引 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 

问题:我们如何使用来自系列s 的值设置数据框df 的列2 中的值?

换句话说,只有数据帧df 中的索引('Tom', 'AAPL')('Tom', 'NFLX) 的值应分别设置为9911('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)

【问题讨论】:

  • John, AAPLJohn, NFLX 不也应该改吗?
  • 更改仅适用于Tom,我尝试使用df.loc[idx['Tom', :], 2] = s 指定

标签: python python-3.x pandas dataframe multi-index


【解决方案1】:

Series 中创建MultiIndex MultiIndex.from_productSeries.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

【讨论】:

  • 如果原始df 的值不是0,这是否有效?
  • @Nyxynyx - 当然,因为 df[2] = s.fillna(df[2]) 将不匹配的值替换为原始值
【解决方案2】:

index.get_level_valuesloc 一起使用:

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

【讨论】:

  • 嗯,s = pd.Series([99, 11], index=['NFLX','AAPL']) 呢?
  • 是的,你是对的,需要有匹配的索引。编辑@jezrael
  • 每日上限,未见 ;)
【解决方案3】:

您可以通过设置“名称”列并使用下面的合并来做到这一点

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

【讨论】:

    猜你喜欢
    • 2017-03-11
    • 1970-01-01
    • 2018-01-18
    • 2019-04-13
    • 2021-11-22
    • 2017-03-24
    • 1970-01-01
    • 2021-11-13
    • 2019-04-06
    相关资源
    最近更新 更多