You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Pandas中基于DataFrame的列与索引值引用并使用字典中的值进行计算

如何在Pandas中基于DataFrame的列与索引值引用并使用字典中的值进行计算

嗨,我来帮你解决这个问题!你遇到的TypeError: unhashable type: 'Index'是因为你试图用整个索引序列去查字典,而字典只接受单个可哈希的键值,不是序列。咱们一步步来搞定它:

先分析错误原因

你的代码里dic[col + "_" + df.index.strftime("%Y")]这部分,df.index.strftime("%Y")返回的是一个Index对象(比如Index(['2019', '2020', '2021'], dtype='object')),把它和列名拼接后得到的还是一个序列,而字典的键必须是单个字符串,所以直接用这个序列查字典就会报错。

解决方案:逐个匹配字典键

我们需要为每个单元格生成对应的字典键,然后获取对应的人口值再做除法。这里有两种常用方法:

方法一:逐列循环处理(直观易懂)

先把非数值的"Unk"转换成NaN,避免计算错误,然后为每一行生成对应的字典键,再从字典中取值计算:

import pandas as pd

# 初始化你的数据
data = [{'A': 1, 'B': 3}, {'A': 2, 'B': 20}, {'A': "Unk", 'B': 50}]
df = pd.DataFrame(data, index=[pd.to_datetime("2019-12-31"),
                               pd.to_datetime("2020-12-30"),
                               pd.to_datetime("2021-12-31")])
dic = {"A_2019": 100, "B_2019": 200, "A_2020": 120, "B_2020": 150}

# 第一步:把"A"列的"Unk"转为NaN,方便后续数值计算
df['A'] = pd.to_numeric(df['A'], errors='coerce')

# 第二步:逐列计算比例
for col in df.columns:
    # 为当前列的每一行生成对应的字典键(比如"A_2019")
    population_keys = [f"{col}_{year}" for year in df.index.year]
    # 从字典中获取人口值,没有对应键的话返回NaN
    populations = pd.Series([dic.get(key) for key in population_keys], index=df.index)
    # 计算新列:原数值除以人口
    df[f"{col}1"] = df[col] / populations

# 查看结果(保留三位小数)
print(df.round(3))

运行后得到的结果正好是你想要的:

A   B     A1     B1
2019-12-31  1.0   3  0.010  0.015
2020-12-30  2.0  20  0.017  0.133
2021-12-31  NaN  50    NaN  0.333

方法二:向量化处理(更高效,适合大数据集)

用stack和unstack把DataFrame转成多层索引的Series,一次性处理所有元素,再转回原结构:

import pandas as pd

# 初始化数据(同上)
data = [{'A': 1, 'B': 3}, {'A': 2, 'B': 20}, {'A': "Unk", 'B': 50}]
df = pd.DataFrame(data, index=[pd.to_datetime("2019-12-31"),
                               pd.to_datetime("2020-12-30"),
                               pd.to_datetime("2021-12-31")])
dic = {"A_2019": 100, "B_2019": 200, "A_2020": 120, "B_2020": 150}

# 转成多层索引Series,方便统一处理
stacked_df = df.stack()
# 为每个元素生成字典键:(日期, 列名) → "列名_年份"
keys = stacked_df.index.map(lambda x: f"{x[1]}_{x[0].year}")
# 计算比例:原数值 / 对应人口(没有人口则返回NaN)
rates = stacked_df / keys.map(dic.get)
# 把结果转回DataFrame,和原数据合并
df = df.join(rates.unstack().add_suffix("1"))

print(df.round(3))

这个方法避免了循环,在处理大型DataFrame时性能更好。

额外说明

  • 用dic.get(key)而不是直接dic[key],是为了当字典中没有对应键(比如2021年的A和B)时,自动返回None,计算时会变成NaN,符合你想要的结果。
  • 先把"Unk"转成NaN是因为字符串无法和数值做除法,转换后计算会自动得到NaN,不影响其他数值的计算。

备注:内容来源于stack exchange,提问作者DrWhat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 18:20:26