我正在尝试使用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")
相反,当我使用this(单独的条件表示为[.]而不是\。显示预期值。
val s1 = sqlContext.sql("select split(val, '[.]')[0] as firstPartSQL from temp")
你知道为什么会这样吗?
当您在带有双引号spark.sql(".....")
的spark-sql中使用regex模式时,它被视为另一个字符串中的字符串,因此会发生两件事。考虑这个
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的regex字符串直接传递给split字符串,因此您只需要单独转义反斜杠(\)。
但当涉及到spark-sql时,模式首先被转换为字符串,然后再次作为字符串传递给split()函数,因此,在sparksql中使用\.
之前,您需要获得它
获得这一点的方法是再添加2个
scala> "\."
res12: String = .
scala> "\\."
res13: String = \.
scala>
如果您只是在spark-sql中传递"\."
,首先它会被转换为.
,然后转换为".",在regex上下文中,它会变成(.)"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>