pandas - 如何从多重索引列中获取值

给定一个具有多重索引列的 pandas DataFrame,如何为每个城市添加一列,该列的值取自与 Code2 字符串映射的 Code 对应的 H 值?

例如,对于以下 DataFrame:

+---+----+------+-----+------+
| H | Nu | City | Code | Code2 |
+---+----+------+-----+------+
| 0.965392 | 15 | Madrid | es | es |
| 0.920614 | 15 | Madrid | it | es |
| 0.726219 | 16 | Madrid | tn | es |
| 0.739119 | 17 | Madrid | fr | es |
| 0.789923 | 55 | Dublin | mt | en |
| 0.699239 | 57 | Dublin | en | en |
| 0.890462 | 68 | Dublin | ar | en |
| 0.746863 | 68 | Dublin | pt | en |
| 0.789923 | 55 | Milano | it | it |
| 0.699239 | 57 | Milano | es | it |
| 0.890462 | 68 | Milano | ar | it |
| 0.746863 | 68 | Milano | pt | it |
+---+----+------+-----+------+

期望的输出是:

+---+----+------+-----+------+-------+
| H | Nu | City | Code | Code2 | HCode |
+---+----+------+-----+------+-------+
| 0.965392 | 15 | Madrid | es | es | 0.965392 |
| 0.920614 | 15 | Madrid | it | es | 0.965392 |
| 0.726219 | 16 | Madrid | tn | es | 0.965392 |
| 0.739119 | 17 | Madrid | fr | es | 0.965392 |
| 0.789923 | 55 | Dublin | mt | en | 0.699239 |
| 0.699239 | 57 | Dublin | en | en | 0.699239 |
| 0.890462 | 68 | Dublin | ar | en | 0.699239 |
| 0.746863 | 68 | Dublin | pt | en | 0.699239 |
| 0.789923 | 55 | Milano | it | it | 0.789923 |
| 0.699239 | 57 | Milano | es | it | 0.789923 |
| 0.890462 | 68 | Milano | ar | it | 0.789923 |
| 0.746863 | 68 | Milano | pt | it | 0.789923 |
+---+----+------+-----+------+-------+

解决方案

方法一:

  1. 使用 groupby()first() 方法对 DataFrame 按 CityCode2 列分组,并获取 H 列的第一个值。
  2. 将分组后的结果与原始 DataFrame 合并,使用 left_onright_on 参数指定连接键。
  3. 使用 ffill() 方法填充合并后的 DataFrame 中的缺失值。
import pandas as pd

# 初始DataFrame
df = pd.DataFrame({
    
    
    'H': [0.965392, 0.920614, 0.726219, 0.739119, 0.789923, 0.699239, 0.890462, 0.746863, 0.789923, 0.699239, 0.890462, 0.746863],
    'Nu': [15, 15, 16, 17, 55, 57, 68, 68, 55, 57, 68, 68],
    'City': ['Madrid', 'Madrid', 'Madrid', 'Madrid', 'Dublin', 'Dublin', 'Dublin', 'Dublin', 'Milano', 'Milano', 'Milano', 'Milano'],
    'Code': ['es', 'it', 'tn', 'fr', 'mt', 'en', 'ar', 'pt', 'it', 'es', 'ar', 'pt'],
    'Code2': ['es', 'es', 'es', 'es', 'en', 'en', 'en', 'en', 'it', 'it', 'it', 'it']
})

# 分组并获取H列的第一个值
gp = df.groupby(['City', 'Code2'])['H'].first().reset_index()

# 合并数据
df = df.merge(gp, left_on=['City', 'Code'], right_on=['City', 'Code2'], how='left')

# 填充缺失值
df['HCode'] = df['H_y'].ffill()

# 删除多余列
df = df.drop('H_y', axis=1)

# 打印结果
print(df)

方法二:

  1. 使用 groupby()apply() 方法对 DataFrame 按 City 列分组,并获取每个组中满足 Code2 等于 Code 条件的行的 H 值。
  2. 将分组后的结果与原始 DataFrame 合并,使用 left_onright_on 参数指定连接键。
  3. 使用 ffill() 方法填充合并后的 DataFrame 中的缺失值。
# 初始DataFrame
df = pd.DataFrame({
    
    
    'H': [0.965392, 0.920614, 0.726219, 0.739119, 0.789923, 0.699239, 0.890462, 0.746863, 0.789923, 0.699239, 0.890462, 0.746863],
    'Nu': [15, 15, 16, 17, 55, 57, 68, 68, 55, 57, 68, 68],
    'City': ['Madrid', 'Madrid', 'Madrid', 'Madrid', 'Dublin', 'Dublin', 'Dublin', 'Dublin', 'Milano', 'Milano', 'Milano', 'Milano'],
    'Code': ['es', 'it', 'tn', 'fr', 'mt', 'en', 'ar', 'pt', 'it', 'es', 'ar', 'pt'],
    'Code2': ['es', 'es', 'es', 'es', 'en', 'en', 'en', 'en', 'it', 'it', 'it', 'it']
})

# 分组并获取满足条件的H值
gp = df.groupby('City').apply(lambda x: x[x['Code2'] == x['Code']]['H'].values[0])

# 合并数据
df['HCode'] = df['City'].map(gp)

# 填充缺失值
df['HCode'] = df['HCode'].ffill()

# 打印结果
print(df)