使用regexp_extract pyspark从字符串中提取年份

eoigrqb6  于 2023-02-09  发布在  Apache
关注(0)|答案(4)|浏览(214)

这是我的结果的一部分:

Grumpier Old Men (1995)
Death Note: Desu nôto (2006–2007)
Irwin & Fran 2013
9500 Liberty (2009)
Captive Women (1000 Years from Now) (3000 A.D.) (1952)
The Garden of Afflictions 2017
The Naked Truth (1957) (Your Past Is Showing) 
Conquest 1453 (Fetih 1453) (2012)
Commune, La (Paris, 1871) (2000)

返回:

1995
2006
2013
2009
1952
2017
1957
1453<--
1871<--

正如你可以看到,从上面,最后2个标题是错误的结果.
这是我的代码:

import pyspark.sql.functions as F

from pyspark.sql.functions import regexp_extract,col

bracket_regexp = "((?<=\()\d{4}(?=[^\(]*$))"

movies_DF=movies_DF.withColumn('yearOfRelease', regexp_extract("title", bracket_regexp + "|(\d{4}$)", 0))

movies_DF.display(10000)

我正在尝试获取标题字符串的年份部分。

06odsfpq

06odsfpq1#

您可以尝试使用以下正则表达式:r'(?<=\()(\d+)(?=\))',其灵感来自于this excellent answer
例如:

movies_DF = movies_DF.withColumn('uu', regexp_extract(col("title"), r'(?<=\()(\d+)(?=\))',1))
 
+------------------------------------------------------------+----+
|title                                                       |uu  |
+------------------------------------------------------------+----+
|Grumpier Old Men (1995)                                     |1995|
|Happy Anniversary (1959)                                    |1959|
|Paths (2017)                                                |2017|
|The Three Amigos - Outrageous! (2003)                       |2003|
|L'obsession de l'or (1906)                                  |1906|
|Babe Ruth Story, The (1948)                                 |1948|
|11'0901 - September 11 (2002)                               |2002|
|Blood Trails (2006)                                         |2006|
|Return to the 36th Chamber (Shao Lin da peng da shi) (1980) |1980|
|Off and Running (2009)                                      |2009|
+------------------------------------------------------------+----+
ee7vknir

ee7vknir2#

根据经验,下面的正则表达式模式似乎是有效的:

(?<=[( ])\d{4}(?=\S*\)|$)

这是一个可以正常工作的regex demo
更新PySpark代码:

bracket_regexp = "((?<=[( ])\d{4}(?=\S*\)|$))"
movies_DF = movies_DF.withColumn('yearOfRelease', regexp_extract("title", bracket_regexp + "|(\d{4}$)", 0))
movies_DF.display(10000)

正则表达式模式通过匹配以下项来工作:

  • (?<=[( ])Assert前面的是(还是空格
  • \d{4}匹配4位数年份
  • (?=\S*\)|$)Assert)(可能以非空格开头)跟随或跟随字符串结尾
erhoui1w

erhoui1w3#

下面是一个可行的正则表达式:

df = df.withColumn("year", F.regexp_extract("title",  "(?:[\s\(])(\d{4})(?:[–\)])?", 1))

对于你提供的例子来说绝对是大材小用,但是我想避免在标题中捕捉到其他数字。另外,你的正则表达式不起作用,因为在你的例子中,并不是所有的年份都用括号括起来,有时你在括号里有非数字字符。

umuewwlo

umuewwlo4#

你的正则表达式只能在第一行起作用。\(\d{4}\)试图匹配一个(,4位数和一个)。对于第一行,你有(1995),这是可以的。其他行不包含这种模式。
在您的情况下,我们可以使用lookbehind和lookahead模式来检测方括号内的日期。(?<=\()表示前面的左方括号。(?=([^\)]+\d{4})*\))表示后面的右方括号(可选的其他日期序列),以处理此(2006–2007)。覆盖了方括号之间的日期后,可以覆盖字符串末尾不带方括号的日期:\d{4}$.

bracket_regex = "((?<=\()\d{4}(?=([^\)]+\d{4})*\)))"

movies_DF\
    .withColumn('uu', regexp_extract("title", bracket_regex + "|(\d{4}$)", 0))\
    .show(truncate=False)
+------------------------------------------------------+----+
|title                                                 |uu  |
+------------------------------------------------------+----+
|Grumpier Old Men (1995)                               |1995|
|Death Note: Desu nôto (2006–2007)                  |2006|
|Irwin & Fran 2013                                     |2013|
|9500 Liberty (2009)                                   |2009|
|test 1234 test 4567                                   |4567|
|Captive Women (1000 Years from Now) (3000 A.D.) (1952)|1952|
|The Garden of Afflictions 2017                        |2017|
|The Naked Truth (1957) (Your Past Is Showing)         |1957|
+------------------------------------------------------+----+

此外,当您将正则表达式传递给spark函数时,不需要在字符串前面加上r

相关问题