PySpark逗号分隔值字典映射报错:TypeError: unhashable type: 'Column'
PySpark 数值映射文本解决方法
错误原因
你遇到的TypeError: unhashable type: 'Column',是因为直接用Python字典去索引PySpark的Column对象导致的。PySpark的Column是分布式计算的逻辑列,不是具体的Python数值类型,而字典的键必须是可哈希的基本类型(如字符串、整数),所以无法直接用Column作为字典键进行查找。
正确解法
方法一:纯PySpark内置函数(推荐,高效无数据拉取)
不需要将lookup表转成本地字典,直接用PySpark的内置函数完成映射,适合大数据场景:
from pyspark.sql import functions as F from pyspark.sql.types import StringType # 1. 将lookup表转为可广播的键值对映射(ID转字符串,匹配split后的数组元素类型) lookup_broadcast = F.broadcast(df_lookup.withColumn("ID", F.col("ID").cast(StringType()))) # 2. 拆分偏好列、映射文本、合并为逗号分隔字符串 df_result = df_data.withColumn("prefs_array", F.split(F.col("Preferences"), ",")) \ .withColumn( "prefs_text_array", F.transform( F.col("prefs_array"), lambda x: F.lookup(lookup_broadcast, x, "ID", "Category") ) ) \ .withColumn("Preferences_text", F.array_join(F.col("prefs_text_array"), ",")) \ .drop("prefs_array", "prefs_text_array") df_result.show()
方法二:广播字典+UDF
如果习惯用字典映射,需将字典广播到Executor(避免重复传输),再通过UDF完成映射:
from pyspark.sql import functions as F from pyspark.sql.types import ArrayType, StringType # 1. 收集lookup表为字典(ID转字符串)并广播 lookup_dict = {str(row.ID): row.Category for row in df_lookup.collect()} broadcast_lookup = spark.sparkContext.broadcast(lookup_dict) # 2. 定义UDF处理数组映射 def map_prefs(prefs_array): return [broadcast_lookup.value.get(pref, pref) for pref in prefs_array] map_prefs_udf = F.udf(map_prefs, ArrayType(StringType())) # 3. 处理数据 df_result = df_data.withColumn("prefs_array", F.split(F.col("Preferences"), ",")) \ .withColumn("prefs_text_array", map_prefs_udf(F.col("prefs_array"))) \ .withColumn("Preferences_text", F.array_join(F.col("prefs_text_array"), ",")) \ .drop("prefs_array", "prefs_text_array") df_result.show()
两种方法最终都能得到目标结果:
| Name | Preferences | Preferences_text |
|---|---|---|
| Tom | 1,3,2 | Politics,Sports,Entertainment |
内容的提问来源于stack exchange,提问作者nic
相关产品推荐
相关产品推荐

