Spark:将单分隔符分隔字符串转为键值对DataFrame列
解决方案
一、基于固定键列表的实现
如果已知所有可能的键名,这个方案直接高效:
- 先将字符串按空格拆分为数组:
import org.apache.spark.sql.functions._ // 示例数据 val df = spark.createDataFrame(Seq( ("key1 val1 key2 val2 key3 val3"), ("key1 val4 key2 val5 key3 val6") )).toDF("raw_str") val split_df = df.withColumn("split_arr", split(col("raw_str"), "\\s+"))
- 针对每个固定键提取对应值:
假设固定键列表为["key1", "key2", "key3"],通过定位键在数组中的索引,取其下一个元素作为对应值:
val key_list = List("key1", "key2", "key3") val result_df = key_list.foldLeft(split_df) { (temp_df, key) => temp_df.withColumn(key, element_at(col("split_arr"), array_position(col("split_arr"), key) + 1)) }.drop("raw_str", "split_arr") result_df.show()
输出结果:
+----+----+----+ |key1|key2|key3| +----+----+----+ |val1|val2|val3| |val4|val5|val6| +----+----+----+
二、动态处理未知键名和数量
如果键的名称、数量不确定,需先收集所有唯一键,再动态生成列:
- 拆分字符串为数组,生成键值对结构:
利用zip_with将数组中偶数索引(键)和奇数索引(值)配对(Spark数组为0-based):
val split_df = df.withColumn("split_arr", split(col("raw_str"), "\\s+")) // 生成键值对数组:取偶数索引元素为key,奇数索引元素为value val kv_df = split_df.withColumn( "kv_pairs", zip_with( slice(col("split_arr"), 1, size(col("split_arr")), 2), // 提取所有键(对应0-based的0、2、4...位) slice(col("split_arr"), 2, size(col("split_arr")), 2), // 提取所有值(对应0-based的1、3、5...位) (k, v) => struct(k.as("key"), v.as("value")) ) )
- 展开键值对并通过pivot生成列:
// 若原数据有唯一行标识(如id列),需替换groupBy的参数为该列,避免行数据聚合 val exploded_df = kv_df.select(explode(col("kv_pairs")).as("kv")) val final_df = exploded_df.groupBy() .pivot(col("kv.key")) .agg(first(col("kv.value"))) final_df.show()
注意事项
- 若行内存在重复键,可将
first替换为collect_list保留所有值,或根据业务需求选择聚合函数 - 拆分时用
\\s+而非,避免连续空格产生空元素
内容的提问来源于stack exchange,提问作者Patrick
相关产品推荐
相关产品推荐

