如何在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
相关产品推荐
相关产品推荐

