Spark Scala - проблема с синтаксисом разбивающей строки - PullRequest
0 голосов
/ 08 января 2019

я пытаюсь разбить строку в столбце DataFrame, используя SparkSQL и Scala, и, кажется, есть разница в том, как условие разделения работает два

Используя Scala,

Это работает -

val seq = Seq("12.1")
val df = seq.toDF("val")

Scala Code ->

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")

Есть идеи, почему это происходит?

1 Ответ

0 голосов
/ 08 января 2019

Когда вы используете шаблоны регулярных выражений в 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, шаблон сначала преобразуется в строку, а затем снова передается как функция string в split (), Поэтому вам нужно получить \\. перед тем, как использовать его в spark-sql

Способ получить это добавить еще 2 \

scala> "\\."
res12: String = \.

scala> "\\\\."
res13: String = \\.

scala>

Если вы просто передадите "\\." в spark-sql, сначала он преобразуется в \., а затем в ".", Который в контексте регулярного выражения становится (.) "Любым" символом то есть разделить на любой символ, и так как каждый символ находится рядом друг с другом, вы получите массив пустой строки. Длина строки "12.1" равна четырем, и она также соответствует конечной границе "$" строки .. так что до разделения (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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...