Scala 如何在逗号(,)处拆分字符串,但忽略双引号(“,”内的逗号)

Scala 如何在逗号(,)处拆分字符串,但忽略双引号(“,”内的逗号),scala,apache-spark,dataframe,rdd,case-class,Scala,Apache Spark,Dataframe,Rdd,Case Class,我有一个文本文件字符串,格式如下: "1","1st",1,"Allen, Miss Elisabeth Walton",29.0000,"Southampton","St Louis, MO","B-5","24160 L221","2","female" 我想在逗号(,)处拆分字符串,但忽略双引号(“”)内的逗号(,)。我使用Spark、Scala和case类创建数据帧。 我尝试了以下代码,但出现错误: val tit_rdd = td.map(td=>td.split(",(?=(

我有一个文本文件字符串,格式如下:

"1","1st",1,"Allen, Miss Elisabeth Walton",29.0000,"Southampton","St Louis, MO","B-5","24160 L221","2","female"
我想在逗号(,)处拆分字符串,但忽略双引号(“”)内的逗号(,)。我使用Spark、Scala和case类创建数据帧。 我尝试了以下代码,但出现错误:

val tit_rdd = td.map(td=>td.split(",(?=([^\\\"]*\\\"[^\\\"]*\\\")*[^\\\"]*$)")).map(td=>tit(td(0).replaceAll("\"","").toInt ,
                                                            td(1).replaceAll("\"",""),
                                                            td(2).toInt,
                                                            td(3).replaceAll("\"",""),
                                                            td(4).toDouble,
                                                            td(5).replaceAll("\"",""),
                                                            td(6).replaceAll("\"",""),
                                                            td(7).replaceAll("\"",""),
                                                            td(8).replaceAll("\"",""),
                                                            td(9).replaceAll("\"","").toInt,
                                                            td(10).replaceAll("\"","")))
案例类别代码如下所示:

case class tit (Num: Int, Class: String, Survival_Code: Int, Name: String, Age: Double, Province: String, Address: String, Coach_No: String, Coach_ID: String, Floor_No:Int, Gender:String)
错误:

17/05/21 14:52:39 ERROR Executor: Exception in task 0.0 in stage 1.0 (TID 1)
java.lang.NumberFormatException: For input string: ""
    at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
    at java.lang.Integer.parseInt(Integer.java:592)
    at java.lang.Integer.parseInt(Integer.java:615)
    at scala.collection.immutable.StringLike$class.toInt(StringLike.scala:272)
    at scala.collection.immutable.StringOps.toInt(StringOps.scala:29)
    at $line27.$read$$iw$$iw$$iw$$iw$$iw$$iw$$iw$$iw$$iw$$iw$$anonfun$2.apply(<console>:40)
    at $line27.$read$$iw$$iw$$iw$$iw$$iw$$iw$$iw$$iw$$iw$$iw$$anonfun$2.apply(<console>:31)
    at scala.collection.Iterator$$anon$11.next(Iterator.scala:409)
    at scala.collection.Iterator$$anon$11.next(Iterator.scala:409)
    at scala.collection.Iterator$$anon$11.next(Iterator.scala:409)
    at org.apache.spark.sql.execution.SparkPlan$$anonfun$4.apply(SparkPlan.scala:247)
    at org.apache.spark.sql.execution.SparkPlan$$anonfun$4.apply(SparkPlan.scala:240)
    at org.apache.spark.rdd.RDD$$anonfun$mapPartitionsInternal$1$$anonfun$apply$24.apply(RDD.scala:784)
    at org.apache.spark.rdd.RDD$$anonfun$mapPartitionsInternal$1$$anonfun$apply$24.apply(RDD.scala:784)
    at org.apache.spark.rdd.MapPartitionsRDD.compute(MapPartitionsRDD.scala:38)
    at org.apache.spark.rdd.RDD.computeOrReadCheckpoint(RDD.scala:319)
    at org.apache.spark.rdd.RDD.iterator(RDD.scala:283)
    at org.apache.spark.scheduler.ResultTask.runTask(ResultTask.scala:70)
    at org.apache.spark.scheduler.Task.run(Task.scala:85)
    at org.apache.spark.executor.Executor$TaskRunner.run(Executor.scala:274)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:748)
17/05/21 14:52:39错误执行者:第1.0阶段(TID 1)任务0.0中出现异常
java.lang.NumberFormatException:用于输入字符串:“”
位于java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
位于java.lang.Integer.parseInt(Integer.java:592)
在java.lang.Integer.parseInt(Integer.java:615)
在scala.collection.immutable.StringLike$class.toInt(StringLike.scala:272)中
位于scala.collection.immutable.StringOps.toInt(StringOps.scala:29)
在$line27.$read$$iw$$iw$$iw$$iw$$iw$$iw$$iw$$iw$$iw$$iw$$anonfun$2.应用(:40)
在$line27.$read$$iw$$iw$$iw$$iw$$iw$$iw$$iw$$iw$$iw$$iw$$anonfun$2.应用(:31)
位于scala.collection.Iterator$$anon$11.next(Iterator.scala:409)
位于scala.collection.Iterator$$anon$11.next(Iterator.scala:409)
位于scala.collection.Iterator$$anon$11.next(Iterator.scala:409)
位于org.apache.spark.sql.execution.SparkPlan$$anonfun$4.apply(SparkPlan.scala:247)
位于org.apache.spark.sql.execution.SparkPlan$$anonfun$4.apply(SparkPlan.scala:240)
位于org.apache.spark.rdd.rdd$$anonfun$mapPartitionsInternal$1$$anonfun$apply$24.apply(rdd.scala:784)
位于org.apache.spark.rdd.rdd$$anonfun$mapPartitionsInternal$1$$anonfun$apply$24.apply(rdd.scala:784)
在org.apache.spark.rdd.MapPartitionsRDD.compute上(MapPartitionsRDD.scala:38)
在org.apache.spark.rdd.rdd.computeOrReadCheckpoint(rdd.scala:319)
位于org.apache.spark.rdd.rdd.iterator(rdd.scala:283)
位于org.apache.spark.scheduler.ResultTask.runTask(ResultTask.scala:70)
位于org.apache.spark.scheduler.Task.run(Task.scala:85)
位于org.apache.spark.executor.executor$TaskRunner.run(executor.scala:274)
位于java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
位于java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
运行(Thread.java:748)

您应该使用Spark的内置功能。

您应该使用Spark的内置功能。

数字格式异常是由于数据中的空数字造成的,您正试图使用
.toInt
将其转换为
整数

解决方法是使用
Try
getOrElse
,如下所示

val tit_rdd = td.map(td=>td.split(",(?=([^\\\"]*\\\"[^\\\"]*\\\")*[^\\\"]*$)"))
  .map(td=>tit(Try(td(0).replaceAll("\"","").toInt) getOrElse 0 ,
  td(1).replaceAll("\"",""),
  Try(td(2).toInt) getOrElse 0,
  td(3).replaceAll("\"",""),
  Try(td(4).toDouble) getOrElse 0.0,
  td(5).replaceAll("\"",""),
  td(6).replaceAll("\"",""),
  td(7).replaceAll("\"",""),
  td(8).replaceAll("\"",""),
  Try(td(9).replaceAll("\"","").toInt) getOrElse 0,
  td(10).replaceAll("\"","")))
这应该可以解决问题

将文本文件转换为
dataFrame
的另一种方法是使用
datatricks csv阅读器

sqlContext.read.format("com.databricks.spark.csv").load("path to the text file")
这将生成默认的
标题名
,如
\u c0
\u c1

您可以做的是将
标题行
放在文本文件中,并将
选项
定义为

sqlContext.read.format("com.databricks.spark.csv").option("header", true).load("path to the text file")

您可以自己使用更多选项

由于数据中的空数字而导致的
NumberFormatException
,您正试图使用
.toInt将其转换为
整数

解决方法是使用
Try
getOrElse
,如下所示

val tit_rdd = td.map(td=>td.split(",(?=([^\\\"]*\\\"[^\\\"]*\\\")*[^\\\"]*$)"))
  .map(td=>tit(Try(td(0).replaceAll("\"","").toInt) getOrElse 0 ,
  td(1).replaceAll("\"",""),
  Try(td(2).toInt) getOrElse 0,
  td(3).replaceAll("\"",""),
  Try(td(4).toDouble) getOrElse 0.0,
  td(5).replaceAll("\"",""),
  td(6).replaceAll("\"",""),
  td(7).replaceAll("\"",""),
  td(8).replaceAll("\"",""),
  Try(td(9).replaceAll("\"","").toInt) getOrElse 0,
  td(10).replaceAll("\"","")))
这应该可以解决问题

将文本文件转换为
dataFrame
的另一种方法是使用
datatricks csv阅读器

sqlContext.read.format("com.databricks.spark.csv").load("path to the text file")
这将生成默认的
标题名
,如
\u c0
\u c1

您可以做的是将
标题行
放在文本文件中,并将
选项
定义为

sqlContext.read.format("com.databricks.spark.csv").option("header", true).load("path to the text file")

您可以自己使用更多选项

您可以使用Spark CSV加载
CSV
数据,其中它处理双引号内的所有逗号

以下是您如何使用它

import org.apache.spark.sql.Encoders

  val spark =
    SparkSession.builder().master("local").appName("test").getOrCreate()

  import spark.implicits._

  val titschema = Encoders.product[tit].schema

  val dfList = spark.read.schema(schema = titschema).csv("data.csv").as[tit]

  dfList.show()

  case class tit(Num: Int,
                 Class: String,
                 Survival_Code: Int,
                 Name: String,
                 Age: Double,
                 Province: String,
                 Address: String,
                 Coach_No: String,
                 Coach_ID: String,
                 Floor_No: Int,
                 Gender: String)
我希望这有帮助

如果要创建与SQLContext.createDataFrame相同的架构 您可以使用Scala反射作为

import org.apache.spark.sql.catalyst.ScalaReflection
val titschema = ScalaReflection.schemaFor[tit].dataType.asInstanceOf[StructType]

您可以使用Spark CSV加载
CSV
数据,其中它处理双引号内的所有逗号

以下是您如何使用它

import org.apache.spark.sql.Encoders

  val spark =
    SparkSession.builder().master("local").appName("test").getOrCreate()

  import spark.implicits._

  val titschema = Encoders.product[tit].schema

  val dfList = spark.read.schema(schema = titschema).csv("data.csv").as[tit]

  dfList.show()

  case class tit(Num: Int,
                 Class: String,
                 Survival_Code: Int,
                 Name: String,
                 Age: Double,
                 Province: String,
                 Address: String,
                 Coach_No: String,
                 Coach_ID: String,
                 Floor_No: Int,
                 Gender: String)
我希望这有帮助

如果要创建与SQLContext.createDataFrame相同的架构 您可以使用Scala反射作为

import org.apache.spark.sql.catalyst.ScalaReflection
val titschema = ScalaReflection.schemaFor[tit].dataType.asInstanceOf[StructType]

我希望这可以帮助您,首先将所有“,”(可拆分)替换为“#”,然后用“#”进行拆分


我希望这可以帮助您,首先将所有“,”(可拆分)替换为“#”,然后用“#”进行拆分