我有多个匹配的正则表达式提取问题

Sar*_*a S 3 pyspark

我试图从字符串 "60 ML of paracetomol and 0.5 ML of XYZ" 中提取 60 ML 和 0.5 ML。该字符串是 spark 数据帧中 X 列的一部分。虽然我能够测试我的正则表达式代码以在正则表达式验证器中提取 60 ML 和 0.5 ML,但我无法使用 regexp_extract 提取它,因为它仅针对第一个匹配项。因此我只得到 60 ML。

你能建议我使用 UDF 的最佳方法吗?

Rya*_*ier 6

以下是使用 python UDF 执行此操作的方法:

from pyspark.sql.types import *
from pyspark.sql.functions import *
import re

data = [('60 ML of paracetomol and 0.5 ML of XYZ',)]
df = sc.parallelize(data).toDF('str:string')

# Define the function you want to return
def extract(s)
    all_matches = re.findall(r'\d+(?:.\d+)? ML', s)
    return all_matches

# Create the UDF, note that you need to declare the return schema matching the returned type
extract_udf = udf(extract, ArrayType(StringType()))

# Apply it
df2 = df.withColumn('extracted', extract_udf('str'))
Run Code Online (Sandbox Code Playgroud)

Python UDF 对本机 DataFrame 操作的性能造成显着影响。稍微考虑一下之后,这里是另一种不使用 UDF 的方法。一般的想法是用逗号替换所有不是您想要的文本,然后在逗号上拆分以创建最终值的数组。如果您只想要数字,您可以更新正则表达式以将“ML”从捕获组中取出。

pattern = r'\d+(?:\.\d+)? ML'
split_pattern = r'.*?({pattern})'.format(pattern=pattern)
end_pattern = r'(.*{pattern}).*?$'.format(pattern=pattern)

df2 = df.withColumn('a', regexp_replace('str', split_pattern, '$1,'))
df3 = df2.withColumn('a', regexp_replace('a', end_pattern, '$1'))
df4 = df3.withColumn('a', split('a', r','))
Run Code Online (Sandbox Code Playgroud)