在 Spark Scala 中,如何使用 locate() 作为参数创建带有 substring() 的列?

In Spark Scala, how to create a column with substring() using locate() as a parameter?

我有一个如下所示的数据集:

val df = Seq("samb id 12", "car id 13", "lxu id 88").toDF("list")

我想创建一个列,该列将是一个仅包含 Id 之后的值的字符串。结果将类似于:

val df_result = Seq(("samb id 12",12), ("car id 13",13), ("lxu id 88",88)).toDF("list", "id_value")

为此,我正在尝试使用 substring。对于提取子串的起始位置参数,我尝试使用locate。但是它给了我一个错误,说它应该是一个 Int 而不是一个列类型。

我正在尝试的是:

df
.withColumn("id_value", substring($"list", locate("id", $"list") + 2, 2))

我得到的错误是:

error: type mismatch;
 found   : org.apache.spark.sql.Column
 required: Int
.withColumn("id_value", substring($"list", locate("id", $"list") + 2, 2))
                                                                 ^

如何解决此问题并继续使用 locate() 作为参数?

更新 更新以提供一个示例,其中@wBob 的回答不适用于我的真实世界数据:我的数据确实比上面的示例复杂一些。

是这样的:

val df = Seq(":option car, lorem :ipsum: :ison, ID R21234, llor ip", "lst ID X49329xas ipsum :ion: ip_s-")

这些值是非常长的字符串,没有特定的模式。

字符串中某处始终是 ID XXXXX 的一部分。 XXXXX 各不相同,但它的大小始终相同(5 个字符)并且始终位于 ID .

之后

我无法使用 splitregexp_extract 来获取此模式中的内容。

不清楚你是想要列表中的第三项还是第一个数字,但这里有几个例子这应该有帮助:

// Assign sample data to dataframe
val df = Seq("samb id 12", "car id 13", "lxu id 88").toDF("list")

df
    .withColumn("t1", split($"list", "\ ")(2))
    .withColumn("t2", regexp_extract($"list", "\d+", 0))
    .withColumn("t3", regexp_extract($"list", "(id )(\d+)", 2))
    .withColumn("t4", regexp_extract($"list", "ID [A-Z](\d{5})", 1))
    .show()

您可以将 splitregexp_extract 等函数与 withColumn 结合使用,以基于现有值创建新列。 split 根据你传入的分隔符将列表拆分成一个数组。我在这里使用了 space ,用两个斜杠转义来拆分数组。该数组是 zero-based 因此指定 2 获取数组中的第三项。 regexp_extract 使用正则表达式从字符串中提取。在这里,我使用 \d 表示数字,+ 与数字 1 或多次匹配。第三列 t3 再次使用具有类似 RegEx 表达式的 regexp_extract,但使用方括号对部分进行分组,并使用 2 从正则表达式中获取第二组,即 (\d+).注意我在正则表达式中使用了额外的斜杠来转义 \d.

中使用的斜杠

我的结果:

如果您的真实数据更复杂,请 post 举几个简单的示例说明此代码不起作用并解释原因。