Pyspark 如何从文本中查找数字
这是我的dataframe中pyspark列(字符串)的一个小示例Pyspark 如何从文本中查找数字,pyspark,Pyspark,这是我的dataframe中pyspark列(字符串)的一个小示例 column | new_column ------------------------------------------------------------------------------------------------- |---
column | new_column
------------------------------------------------------------------------------------------------- |--------------------------------------------------
Hoy es día de ABC/KE98789T983456 clase. | 98789
------------------------------------------------------------------------------------------------- |--------------------------------------------------
Como ABC/KE 34562Z845673 todas las mañanas | 34562
------------------------------------------------------------------------------------------------- |--------------------------------------------------
Hoy tiene ABC/KE 110330/L63868 clase de matemáticas, | 110330
------------------------------------------------------------------------------------------------- |--------------------------------------------------
Marcos se ABC 898456/L56784 levanta con sueño. | 898456
------------------------------------------------------------------------------------------------- |--------------------------------------------------
Marcos se ABC898456 levanta con sueño. | 898456
------------------------------------------------------------------------------------------------- |--------------------------------------------------
comienza ABC - KE 60014 -T60058 | 60014
------------------------------------------------------------------------------------------------- |--------------------------------------------------
inglés y FOR 102658/L61144 ciencia. Se viste, desayuna | 102658
------------------------------------------------------------------------------------------------- |--------------------------------------------------
y comienza FOR ABC- 72981 / KE T79581: el camino hacia la | 72981
------------------------------------------------------------------------------------------------- |--------------------------------------------------
escuela. Se FOR ABC 101665 - 103035 - 101926 - 105484 - 103036 - 103247 - encuentra con su | [101665,103035,101926,105484,103036,103247]
------------------------------------------------------------------------------------------------- |--------------------------------------------------
escuela ABCS 206048/206049/206050/206051/205225-FG-matemáticas- | [206048,206049,206050,206051,205225]
------------------------------------------------------------------------------------------------- |--------------------------------------------------
encuentra ABCS 111553/L00847 & 111558/L00895 - matemáticas | [111553, 111558]
------------------------------------------------------------------------------------------------- |--------------------------------------------------
ciencia ABC 163278/P20447 AND RETROFIT ABCS 164567/P21000 - 164568/P21001 - desayuna | [163278,164567,164568 ]
------------------------------------------------------------------------------------------------- |--------------------------------------------------
ABC/KE 71729/T81672 - 71781/T81674 71782/T81676 71730/T81673 71783/T81677 71784/T | [71729,71781,71782,71730,71783,71784]
------------------------------------------------------------------------------------------------- |--------------------------------------------------
ciencia ABC/KE2646/L61175:E/F-levanta con sueño L61/62LAV AT Z5CTR/XC D3-1593 | [2646]
-----------------------------------------------------------------------------------------------------------------------------------------------------
escuela ABCS 6048/206049/6050/206051/205225-FG-matemáticas- MSN 2345 | [6048,206049,6050,206051,205225]
-----------------------------------------------------------------------------------------------------------------------------------------------------
FOR ABC/KE 109038_L35674_DEFINE AND DESIGN IMPROVEMENTS OF 1618 FROM 118(PDS4 BRACKETS) | [109038]
-----------------------------------------------------------------------------------------------------------------------------------------------------
y comienza FOR ABC- 2981 / KE T79581: el camino hacia la 9856 | [2981]
我想从文本中提取所有包含:4、5或6位数字的数字。
提取它们的条件和案例:
- Attached to ABC/KE (first line in the example above).
- after ABC/KE + space (second and third line).
- after ABC + space (line 4)
- after ABC without space (line 5)
- after ABC - KE + space
- after for word
- after ABC- + space
- after ABC + space
- after ABCS (line 10 and 11)
失败案例示例:
Column | new_column
------------------------------------------------------------------------------------------------------------------------
FOR ABC/KE 109038_L35674_DEFINE AND DESIGN IMPROVEMENTS OF 1618 FROM 118(PDS4 BRACKETS) | [1618] ==> should be [109038]
------------------------------------------------------------------------------------------------------------------------
ciencia ABC/KE2646/L61175:E/F-levanta con sueño L61/62LAV AT Z5CTR/XC D3-1593 | [1593] ==> should be [2646]
------------------------------------------------------------------------------------------------------------------------
escuela ABCS 6048/206049/6050/206051/205225-FG-matemáticas- MSN 2345 | [6048,206049,6050,206051,205225, 2345] ==> should be [6048,206049,6050,206051,205225]
我希望我恢复了案例,您可以看到我上面的示例和预期输出。
我怎么做?
谢谢您使用正则表达式清除数据的单向方法,并设置一个值为
ABC
的单独锚,以确定潜在匹配的开始。在str.split()之后,遍历生成的数组,以标记并检索此锚点后面的连续匹配数字
Edit:在数据模式(\b(\d{4,6})(?=[A-Z/|]|$)
)中添加了下划线\u
,以便现在允许下划线作为锚定符跟随匹配的4-6位子字符串。这修正了第一行,第2行和第3行应该使用现有的正则表达式模式
import re
from pyspark.sql.types import ArrayType, StringType
from pyspark.sql.functions import udf
(1) 使用正则表达式模式清除原始数据,这样我们就只有一个锚ABC
来确定潜在匹配的开始:
- clean1:使用
将'&'、'-'和空格转换为空格[-&\s]+
,它们用于连接数字链'
example: `ABC - KE` --> `ABC KE` `103035 - 101926 - 105484` -> `103035 101926 105484` `111553/L00847 & 111558/L00895` -> `111553/L00847 111558/L00895`
- clean2:将匹配以下三个子模式的文本转换为
'ABC'
+ ABCS?(?:[/\s]+KE|(?=\s*\d)) + ABC followed by an optional `S` + followed by at least one slash or whitespace and then `KE` --> `[/\s]+KE` example: `ABC/KE 110330/L63868` to `ABC 110330/L63868` + or followed by optional whitespaces and then at least one digit --> (?=\s*\d) example: ABC898456 -> `ABC 898456` + \bFOR\s+(?:[A-Z]+\s+)* + `FOR` words example: `FOR DEF HJK 12345` -> `ABC 12345`
- 数据:\b(\d{4,6})(?=[A-Z/|]|$)是与实际数字匹配的正则表达式:4-6位后跟[A-Z/]或_字符串的结尾
ptns = {
'clean1': re.compile(r'[-&\s]+', re.UNICODE)
, 'clean2': re.compile(r'\bABCS?(?:[/\s-]+KE|(?=\s*\d))|\bFOR\s+(?:[A-Z]+\s+)*', re.UNICODE)
, 'data' : re.compile(r'\b(\d{4,6})(?=[A-Z/_]|$)', re.UNICODE)
}
(3) 创建一个函数来查找匹配的数字并将其保存到数组中
def find_number(s_t_r, ptns, is_debug=0):
try:
arr = re.sub(ptns['clean2'], 'ABC ', re.sub(ptns['clean1'], ' ', s_t_r.upper())).split()
if is_debug: return arr
# f: flag to identify if a chain of matches is started, default is 0(false)
f = 0
new_arr = []
# iterate through the above arr and start checking numbers when anchor is detected and set f=1
for x in arr:
if x == 'ABC':
f = 1
elif f:
new = re.findall(ptns['data'], x)
# if find any matches, else reset the flag
if new:
new_arr.extend(new)
else:
f = 0
return new_arr
except Exception as e:
# only use print in local debugging
print('ERROR:{}:\n [{}]\n'.format(s_t_r, e))
return []
(4) 定义了udf函数
udf_find_number = udf(lambda x: find_number(x, ptns), ArrayType(StringType()))
(5) 获取新的_列
df.withColumn('new_column', udf_find_number('column')).show(truncate=False)
+------------------------------------------------------------------------------------------+------------------------------------------------+
|column |new_column |
+------------------------------------------------------------------------------------------+------------------------------------------------+
|Hoy es da de ABC/KE98789T983456 clase. |[98789] |
|Como ABC/KE 34562Z845673 todas las ma?anas |[34562] |
|Hoy tiene ABC/KE 110330/L63868 clase de matem篓垄ticas, |[110330] |
|Marcos se ABC 898456/L56784 levanta con sue?o. |[898456] |
|Marcos se ABC898456 levanta con sue?o. |[898456] |
|comienza ABC - KE 60014 -T60058 |[60014] |
|ingl篓娄s y FOR 102658/L61144 ciencia. Se viste, desayuna |[102658] |
|y comienza FOR ABC- 72981 / KE T79581: el camino hacia la |[72981] |
|escuela. Se FOR ABC 101665 - 103035 - 101926 - 105484 - 103036 - 103247 - encuentra con su|[101665, 103035, 101926, 105484, 103036, 103247]|
|escuela ABCS 206048/206049/206050/206051/205225-FG-matem篓垄ticas- |[206048, 206049, 206050, 206051, 205225] |
|encuentra ABCS 111553/L00847 & 111558/L00895 - matem篓垄ticas |[111553, 111558] |
|ciencia ABC 163278/P20447 AND RETROFIT ABCS 164567/P21000 - 164568/P21001 - desayuna |[163278, 164567, 164568] |
|ABC/KE 71729/T81672 - 71781/T81674 71782/T81676 71730/T81673 71783/T81677 71784/T |[71729, 71781, 71782, 71730, 71783, 71784] |
+------------------------------------------------------------------------------------------+------------------------------------------------+
(6) 调试代码,使用find_number(row.column,ptn,1)
检查前两个正则表达式模式是否按预期工作:
for row in df.limit(10).collect():
print('{}:\n {}\n'.format(row.column, find_number(row.column, ptns)))
一些注意事项:
- 在
模式中,ABC和ABS的处理方式相同。如果它们不同,只需删除“S”,并在模式末尾添加一个新的备选方案clean2
ABCS\S*(?=\d)
re.compile(r'\bABC(?:[/\s-]+KE|(?=\s*\d))|\bFOR\s+(?:[A-Z]+\s+)*|ABCS\s*(?=\d)')
- 当前模式
仅将“-”、“&”和空格视为连续的连接符,您可以添加更多字符或单词,如“和”、“或”,例如:clean1
re.compile(r'[-&\s]+|\b(?:AND|OR)\b')
是\b对于\s+(?:[A-Z]+\s+*),这可能会根据单词中是否允许数字等进行调整对于单词
- 这是在Python-3上测试的。使用Python-2时,unicode可能会出现问题,您可以使用
“data”:re.compile(r'\b(\d{4,6})(?=[a-Z/|]|$),re.UNICODE)
。我刚刚添加了4-6个数字,因此后面必须跟一个大写字母、斜杠或下划线(上一个数字缺少下划线)。这应该可以解决问题。非常感谢,它工作得很好。我发布了一个新问题,我只是想给这个模式添加一些条件,不要触及旧的案例。所以也许你只能再帮我一次:)谢谢