pandas apply获取字典值报Series不可哈希错误的解决方法
问题说明
需要从存储域名对计数的字典中查询匹配值,为pandas DataFrame生成新列。
使用的计数字典结构如下:
pair_devices_count = {('tWAAAA.jg', 'ttNggB.jg'): 1, ('tWAAAM.jg', 'ttWVsM.jg'): 2, ('tWAAAN.CV', 'ttNggB.AS'): 1, ('tWAAAN.CV', 'ttNggB.CV'): 2, ('tWAAAN.CV', 'ttNggB.QG'): 1}
原写法触发Series不可哈希报错的核心原因:DataFrame的apply方法默认按列遍历(axis=0),传入lambda函数的参数是整列的Series对象,而可变类型的Series无法作为字典的键完成哈希查询。
原错误代码:
train_data[['domain', 'target_domain']].apply(lambda x: pair_devices_count.get((x), 0))
可行实现方案
以下三种方案都可以实现需求,按性能从高到低排序:
- 方案1:向量化匹配(大数据量首选)
将原字典转换为多级索引的Series,通过pandas原生的关联匹配逻辑完成赋值,无逐行循环开销,速度最快:import pandas as pd # 转换字典为带多级域名索引的计数Series ref_s = pd.Series(pair_devices_count, name="pair_devices_count") # 关联匹配到原表,缺失值填充0 train_data = train_data.join( ref_s, on=["domain", "target_domain"] ).fillna({"pair_devices_count": 0}) - 方案2:列表推导式(写法简洁,性能够用)
直接zip两列的值逐对拼元组查字典,写法简单,性能远好于逐行apply,适合中小数据量:train_data["pair_devices_count"] = [ pair_devices_count.get((dom, tgt_dom), 0) for dom, tgt_dom in zip(train_data["domain"], train_data["target_domain"]) ] - 方案3:逐行apply(逻辑直观,适合小数据量)
给apply添加axis=1参数改为按行遍历,此时传入lambda的是单行数据,提取两个字段拼元组查询即可:train_data["pair_devices_count"] = train_data[["domain", "target_domain"]].apply( lambda row: pair_devices_count.get((row["domain"], row["target_domain"]), 0), axis=1 )
内容的提问来源于stack exchange,提问作者MONEY LONGER
相关产品推荐
相关产品推荐

