【问题标题】:How to find a string in each row in a dataframe in pyspark如何在pyspark的数据框中的每一行中查找一个字符串
【发布时间】:2018-06-20 10:40:27
【问题描述】:

这是可用的数据框:

+--------------------+
|                Name|
+--------------------+
|Braund, Mr. Owen ...|
|Cumings, Mrs. Joh...|
|Heikkinen, Miss. ...|
|Futrelle, Mrs. Ja...|
|Allen, Mr. Willia...|
|Moran, Mr. James|
|McCarthy, Mr. Tim...|
|Palsson, Master. ...|
|Johnson, Mrs. Osc...|
+--------------------+

我想使用 Pyspark 在 DATA FRAME 的每一行中查找 Title 和 Surname 的第一个匹配项(Pandas lib 在我的集群中不可用)。

pattern=re.compile(r'(Dr|Mrs?|Ms|Miss|Master|Rev|Capt|Mlle|Col|Major|Sir|Lady|Mme|Don)\\.'
pattern.match(df['Name'])

【问题讨论】:

  • 可能类似于this that uses regexthisudf
  • @mkaran 尝试了这段代码但没有成功 def findTitle(df): rdd=df.select("Name").flatMap(lambda x: x).map(lambda x:x).collect () for f in rdd: title=re.search('(Dr|Mrs?|Ms|Miss|Master|Rev|Capt|Mlle|Col|Major|Sir|Lady|Mme|Don)',f).group ()
  • 你能试试df = df.filter(df["Name"].rlike(r'(Ms|Miss)'))(和df.show())吗?我无法让它与您的正则表达式一起使用,但它绝对可以与这个更简单的表达式一起使用。
  • 顺便说一句,如果你想要你的姓氏,你的正则表达式应该修改为使用lookbehind的东西,例如(?<=Mr\.\s)\w+ 将匹配第一行中的 Owen 等。
  • @mkaran df = df.filter(df["Name"].rlike(r'(Ms|Miss)')) 。我有超过 15 个姓氏的模式。它不适合我要么。

标签: pyspark spark-dataframe


【解决方案1】:

如果Name 列的第一个单词是“姓氏”,那么您可以试试这个,否则正则表达式需要稍作调整。

from pyspark.sql.functions import regexp_extract, col

#sample data
df= sc.parallelize([["Braund, Mr. Owen"], 
                    ["Cumings, Mrs. Joh"], 
                    ["Heikkinen, Miss."], 
                    ["Futrelle, Mrs. Ja"]]).toDF(["Name"])

df = df.withColumn('Surname', regexp_extract(col('Name'), '(\S+),.*', 1))
df.show()

样本数据:

+-----------------+
|             Name|
+-----------------+
| Braund, Mr. Owen|
|Cumings, Mrs. Joh|
| Heikkinen, Miss.|
|Futrelle, Mrs. Ja|
+-----------------+

输出是:

+-----------------+---------+
|             Name|  Surname|
+-----------------+---------+
| Braund, Mr. Owen|   Braund|
|Cumings, Mrs. Joh|  Cumings|
| Heikkinen, Miss.|Heikkinen|
|Futrelle, Mrs. Ja| Futrelle|
+-----------------+---------+

【讨论】:

  • @shalu 也许你应该accept the answer,如果它帮助你解决了你的问题,那么这个问题就可以被认为是关闭了。
  • 我想要像Mr. Miss这样的头衔,确定我一找到答案就会关闭。
【解决方案2】:

您可以按照@Prem 的建议使用regexp_extract,但使用不同的正则表达式模式,具体取决于您的需要:

# do not keep the first two groups, just what follows, the surname:
pattern = r'(?:(?:Dr|Mrs?|Ms|Miss|Master|Rev|Capt|Mlle|Col|Major|Sir|Lady|Mme|Don)\.?\s?)(\w+)'

# or keep both title and surname
pattern_with_title = r'((Dr|Mrs?|Ms|Miss|Master|Rev|Capt|Mlle|Col|Major|Sir|Lady|Mme|Don)\.?\s?)(\w+)'

#sample data
df = spark.createDataFrame([["Braund, Mr. Owen other stuff"], 
                       ["Cumings, Mrs. Joh some details"], 
                       ["Heikkinen, Miss. Hellen blah"], 
                       ["Futrelle, Mrs. Ja .... .... "]], ["Name"])

df.show()

+-----------------+
|             Name|
+-----------------+
| Braund, Mr. Owen|
|Cumings, Mrs. Joh|
| Heikkinen, Miss.|
|Futrelle, Mrs. Ja|
+-----------------+

# create a column with what matches the pattern
df = df.withColumn("Surname", regexp_extract("Name", pattern, 1))

df.show()
# keeps only the Surname
+-----------------+---------+
|             Name|  Surname|
+-----------------+---------+
| Braund, Mr. Owen| Owen    |
|Cumings, Mrs. Joh| Joh     |
| Heikkinen, Miss.| Hellen  |
|Futrelle, Mrs. Ja| Ja      |
+-----------------+---------+

 # in case you want both title and Surname:
 df = df.withColumn("Surname with title", regexp_extract("Name", pattern_with_title, 1))

+-----------------+---------+--------------------+
|             Name|  Surname|  Surname with title|
+-----------------+---------+--------------------+
|Braund, Mr. Owen | Owen    | Mr. Ownen          |
|Cumings, Mrs. Joh| Joh     | Mrs. Joh           |
|Heikkinen, Miss..| Hellen  | Miss. Hellen       |
|Futrelle, Mrs. Ja| Ja      | Mrs. Ja            |
+-----------------+---------+--------------------+

如果您需要全名、姓氏,则稍微更改模式以将它们也包括在内,例如:

main_pattern = r'Dr|Mrs?|Ms|Miss|Master|Rev|Capt|Mlle|Col|Major|Sir|Lady|Mme|Don'

pattern_full = r'(\w+,?\s('+ main_pattern+')\.?\s?\w+)'
pattern_name = r'(?:(?:'+ main_pattern+')\.?\s?)(\w+)'
pattern_title = r'(?:('+ main_pattern+')\.?\s?)'
pattern_surname = r'(\w+)(?:\,\s?(?:'+ main_pattern+')\.?\s?)'

df = df.withColumn("Full Name", regexp_extract("Name", pattern_full, 1))
df = df.withColumn("First Name", regexp_extract("Name", pattern_name, 1))
df = df.withColumn("Surname", regexp_extract("Name", pattern_surname, 1))
df = df.withColumn("Title", regexp_extract("Name", pattern_title, 1))

df.show(10, False)

+------------------------------+-----------------------+----------+------------+-----+
|Name                          |Full Name              |Surname   |First Name  |Title|
+------------------------------+-----------------------+----------+------------+-----+
|Braund, Mr. Owen other stuff  |Braund, Mr. Owen       |Braund    |Owen        |Mr   |
|Cumings, Mrs. Joh some details|Cumings, Mrs. Joh      |Cumings   |Joh         |Mrs  |
|Heikkinen, Miss. Hellen blah  |Heikkinen, Miss. Hellen|Heikkinen |Hellen      |Miss |
|Futrelle, Mrs. Ja .... ....   |Futrelle, Mrs. Ja      |Futrelle  |Ja          |Mrs  |
+------------------------------+-----------------------+----------+------------+-----+

这完全是关于在正则表达式中忽略哪个部分和选择哪个部分。希望这会有所帮助,祝你好运!

注意:不是最佳的正则表达式,它还有改进的空间。

【讨论】:

  • 但我需要 +-----+----------+---------- ----------+ |姓名|姓氏|标题| +-----------------+---------+--------+ |布劳德,欧文先生 |欧文 |先生| |卡明斯,约翰夫人|乔 |夫人| |海基宁,小姐..|海伦 |小姐。 |富特雷尔,贾太太|贾 |夫人 | +-----------------+---------
  • @shalu,你的问题不清楚,你能更新一下吗?我已经更新了答案以包含许多不同的组合,如果它涵盖了您的问题,请告诉我。谢谢
  • 我更新了它。我希望在每一行中第一次出现标题和姓氏。姓氏和标题的模式是明确提供的。
  • @shalu 谢谢!我看到我有姓氏的另一种方式。我已经更新了我的答案。它是否满足您的需求?
  • 谢谢,这是我想要的标题栏。是的,它满足了我的要求。
猜你喜欢
  • 1970-01-01
  • 2015-05-11
  • 1970-01-01
  • 2014-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多