You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PySpark读取文本数据转DataFrame问题求助(未找到对应方案)

搞定Spark读取带空格字段的CSV数据

嘿,看你提供的这段ICD疾病编码数据,前3个是短标识字段,后面俩是带空格的疾病名称,直接用默认CSV读取肯定会把字段内的空格当成分隔符,导致数据错乱。我给你几个实用的解决方案,都是实际项目里验证过的:

先贴下你的原始数据样例:

00001 A00 0 Cholera Cholera
00002 A000 1 Cholera due to Vibrio cholerae 01 biovar cholerae Cholera due to Vibrio cholerae 01 biovar cholerae
00003 A001 1 Cholera due to Vibrio cholerae 01 biovar eltor Cholera due to Vibrio cholerae 01 biovar eltor
00004 A009 1 Cholera unspecified Cholera unspecified

方案1:优先确认分隔符——大概率是制表符

很多医疗类数据会用制表符做分隔,避免字段内空格干扰。如果你的数据是这种情况,直接指定分隔符就行,Spark 2.0+之后不用第三方包,官方CSV读取器足够好用:

// Spark 2.0+ 官方写法
val data = spark.read
  .option("delimiter", "\t") // 把分隔符设为制表符
  .option("header", "false") // 你的数据没有表头
  .option("inferSchema", "true") // 让Spark自动推断字段类型,省得手动写Schema
  .csv("你的文件路径")

要是你还在用老版本Spark,把spark.read换成sqlContext.read.format("com.databricks.spark.csv")就行,其他参数一致。

方案2:固定长度字段用substring硬解析

如果前3个字段是固定长度(比如序号5位、编码3-4位、标识位1位),直接按位置截取最靠谱,完全不受空格干扰:

import org.apache.spark.sql.types._

// 先按纯文本读入每一行原始数据
val rawData = spark.read.text("你的文件路径")

// 手动按位置切分并转换字段
val parsedData = rawData.select(
  substring(col("value"), 1, 5).alias("id"), // 第1-5位是序号
  substring(col("value"), 7, 4).alias("code"), // 序号后有空格,从第7位开始取4位(兼容A00/A000两种长度)
  substring(col("value"), 12, 1).cast(IntegerType).alias("flag"), // 编码后有空格,第12位开始取1位转数字
  // 用正则拆分剩余部分:跳过前13位(前3个字段+空格),拆成两个疾病名称
  regexp_extract(col("value"), "^.{13}\\s+(.*?)\\s+(.*)$", 1).alias("disease_name1"),
  regexp_extract(col("value"), "^.{13}\\s+(.*?)\\s+(.*)$", 2).alias("disease_name2")
)

方案3:正则表达式一键分割

要是不想算字段位置,用正则匹配更灵活,直接把整行按规则拆成数组:

val parsedData = rawData.select(
  // 正则规则:开头5位数字→空格→3-4位字母数字→空格→1位数字→空格→两段带空格的文本
  split(col("value"), "^(\\d{5})\\s+(\\w{3,4})\\s+(\\d)\\s+(.*?)\\s+(.*)$", 0).alias("parts")
).select(
  col("parts").getItem(1).alias("id"),
  col("parts").getItem(2).alias("code"),
  col("parts").getItem(3).cast(IntegerType).alias("flag"),
  col("parts").getItem(4).alias("disease_name1"),
  col("parts").getItem(5).alias("disease_name2")
)

小提醒

  • 优先排查分隔符!如果是制表符,方案1最简单,效率也最高;
  • 要是inferSchema速度慢或者类型推断不准,就手动定义StructType,配合cast转换更稳妥;
  • Spark 2.0之后别再用com.databricks.spark.csv了,官方的spark.read.csv功能更全,还不用额外导包。

内容的提问来源于stack exchange,提问作者Lizou

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 08:07:18