在 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
.
之后
我无法使用 split
和 regexp_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()
您可以将 split
和 regexp_extract
等函数与 withColumn
结合使用,以基于现有值创建新列。 split
根据你传入的分隔符将列表拆分成一个数组。我在这里使用了 space ,用两个斜杠转义来拆分数组。该数组是 zero-based 因此指定 2
获取数组中的第三项。 regexp_extract
使用正则表达式从字符串中提取。在这里,我使用 \d
表示数字,+
与数字 1 或多次匹配。第三列 t3
再次使用具有类似 RegEx 表达式的 regexp_extract
,但使用方括号对部分进行分组,并使用 2
从正则表达式中获取第二组,即 (\d+)
.注意我在正则表达式中使用了额外的斜杠来转义 \d
.
中使用的斜杠
我的结果:
如果您的真实数据更复杂,请 post 举几个简单的示例说明此代码不起作用并解释原因。
我有一个如下所示的数据集:
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
.
我无法使用 split
和 regexp_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()
您可以将 split
和 regexp_extract
等函数与 withColumn
结合使用,以基于现有值创建新列。 split
根据你传入的分隔符将列表拆分成一个数组。我在这里使用了 space ,用两个斜杠转义来拆分数组。该数组是 zero-based 因此指定 2
获取数组中的第三项。 regexp_extract
使用正则表达式从字符串中提取。在这里,我使用 \d
表示数字,+
与数字 1 或多次匹配。第三列 t3
再次使用具有类似 RegEx 表达式的 regexp_extract
,但使用方括号对部分进行分组,并使用 2
从正则表达式中获取第二组,即 (\d+)
.注意我在正则表达式中使用了额外的斜杠来转义 \d
.
我的结果:
如果您的真实数据更复杂,请 post 举几个简单的示例说明此代码不起作用并解释原因。