我正在尝试使用SparkSQL和Scala在DataFrame列中拆分String, 而且拆分条件对两者的作用方式似乎有所不同
使用Scala,
这有效-
val seq = Seq("12.1")
val df = seq.toDF("val")
Scala代码->
val seq = Seq("12.1")
val df = seq.toDF("val")
val afterSplit = df2.withColumn("FirstPart", split($"val", "\\.")).select($"FirstPart".getItem(0).as("PartOne"))
afterSplit.show(false)
但是,在我使用Spark SQL时,firstParkSQL显示为空白。
df.registerTempTable("temp")
val s1 = sqlContext.sql("select split(val, '\\.')[0] as firstPartSQL from temp")
相反,当我使用它时(用[。]而不是\表示的单独条件。 期望值出现。
val s1 = sqlContext.sql("select split(val, '[.]')[0] as firstPartSQL from temp")
任何想法为什么会这样?
答案 0 :(得分:1)
在spark-sql中使用双引号spark.sql(".....")
的正则表达式模式时,它被视为另一个字符串中的字符串,因此发生两件事。考虑一下
scala> val df = Seq("12.1").toDF("val")
df: org.apache.spark.sql.DataFrame = [val: string]
scala> df.withColumn("FirstPart", split($"val", "\\.")).select($"FirstPart".getItem(0).as("PartOne")).show
+-------+
|PartOne|
+-------+
| 12|
+-------+
scala> df.createOrReplaceTempView("temp")
使用df(),将split的正则表达式字符串直接传递到split字符串,因此您只需要转义反斜杠(\)。
但是当涉及spark-sql时,该模式首先转换为字符串,然后再次作为字符串传递给split()函数,
因此,您需要先获取\\.
才能在spark-sql中使用
获取方法是再添加2个\
scala> "\\."
res12: String = \.
scala> "\\\\."
res13: String = \\.
scala>
如果仅在spark-sql中传递"\\."
,则首先将其转换为\.
,然后转换为“。”,在正则表达式上下文中它变成(。)“ any”字符
即在任何字符上分割,并且由于每个字符彼此相邻,因此会得到一个空字符串数组。
字符串“ 12.1”的长度为四,并且也与字符串的最后边界“ $”匹配。.因此,直到split(val,'\。')[4],您将获得
空字符串。发出split(val,'\。,')[5]时,您会得到null
要验证这一点,可以将相同的定界符字符串"\\."
传递给regex_replace()函数,看看会发生什么情况
scala> spark.sql("select split(val, '\\.')[0] as firstPartSQL, regexp_replace(val,'\\.','9') as reg_ex from temp").show
+------------+------+
|firstPartSQL|reg_ex|
+------------+------+
| | 9999|
+------------+------+
scala> spark.sql("select split(val, '\\\\.')[0] as firstPartSQL, regexp_replace(val,'\\\\.','9') as reg_ex from temp").show
+------------+------+
|firstPartSQL|reg_ex|
+------------+------+
| 12| 1291|
+------------+------+
scala>
如果您仍然想在df和sql之间使用相同的模式,请使用原始字符串,即三引号。
scala> raw"\\."
res23: String = \\.
scala>
scala> spark.sql("""select split(val, '\\.')[0] as firstPartSQL, regexp_replace(val,'\\.','9') as reg_ex from temp""").show
+------------+------+
|firstPartSQL|reg_ex|
+------------+------+
| 12| 1291|
+------------+------+
scala> spark.sql("""select split(val, "\\.")[0] as firstPartSQL, regexp_replace(val,"\\.",'9') as reg_ex from temp""").show
+------------+------+
|firstPartSQL|reg_ex|
+------------+------+
| 12| 1291|
+------------+------+
scala>