在Spark/Hive中将Hive列字符串转为Int数组并计算统计值
解决方案
核心解决思路:
- 用
transform函数可在不编写UDF的前提下将array[string]转为array[int](Spark 2.4+支持) - 对数组内元素求和、取最大/最小值需用
array_sum/array_max/array_min,而非聚合函数sum(聚合函数sum用于对列的多行值求和,而非数组内部元素)
高版本Spark(2.4+)实现代码
import org.apache.spark.sql.functions._ // 加载Hive表数据 val df = spark.sql("select col1 from table1") // 步骤1:去除字符串末尾的单位(sec/min),提取纯数字分隔字符串 val df_clean = df.withColumn("num_str", regexp_replace(col("col1"), " (sec|min)$", "")) // 步骤2:按-或空格拆分字符串为string数组,再转成int数组 val df_array = df_clean.withColumn("num_array", transform(split(col("num_str"), "[- ]"), x => cast(x as Integer))) // 步骤3:计算每行数组的总和、最大值、最小值 val df_result = df_array.withColumn("sum_val", array_sum(col("num_array"))) .withColumn("max_val", array_max(col("num_array"))) .withColumn("min_val", array_min(col("num_array"))) // 查看最终结果 df_result.show(false)
代码说明
regexp_replace(...):匹配并移除末尾的sec或min,对无单位的400 200这类行无影响,直接保留原字符串split(col("num_str"), "[- ]"):用正则匹配-或空格作为分隔符,将字符串拆分为string类型数组transform(...):遍历数组内每个string元素,强制转换为Integer类型,得到int数组array_sum/array_max/array_min:分别计算数组元素的总和、最大值、最小值
低版本Spark(<2.4)兼容实现
若你的Spark版本不支持transform和array_*系列函数,可通过explode+分组聚合实现:
import org.apache.spark.sql.functions._ import org.apache.spark.sql.types.IntegerType val df = spark.sql("select col1 from table1") // 生成唯一行ID,用于后续分组聚合,同时拆分并转换数字类型 val df_explode = df.withColumn("row_id", monotonically_increasing_id()) .withColumn("num_str", regexp_replace(col("col1"), " (sec|min)$", "")) .withColumn("num", explode(split(col("num_str"), "[- ]"))) .withColumn("num", col("num").cast(IntegerType)) // 按行ID分组,计算每行的总和、最大、最小值 val df_result = df_explode.groupBy("row_id", "col1") .agg(sum("num").alias("sum_val"), max("num").alias("max_val"), min("num").alias("min_val")) df_result.show(false)
内容的提问来源于stack exchange,提问作者nagraj036
相关产品推荐
相关产品推荐

