将正则表达式应用于spark数据帧的每一行,并将其另存为同一数据帧中的新列

时间:2016-08-22 19:44:08

标签: python python-2.7 apache-spark pyspark pyspark-sql

假设我有一个火花数据框,

data.show()

ID                URL
1             https://www.sitename.com/&q=To+Be+Parsed+out&oq=Dont+Need+to+be+parsed
2             https://www.sitename.com/&q=To+Be+Parsed+out&oq=Dont+Need+to+be+parsed
3             https://www.sitename.com/&q=To+Be+Parsed+out&oq=Dont+Need+to+be+parsed
4             https://www.sitename.com/&q=To+Be+Parsed+out&oq=Dont+Need+to+be+parsed
5                 None

我想写一个正则表达式操作,我想解析特定场景的URL。该场景将是在& q之后以及之前和之前解析。我可以在python中为python数据帧写这个,如下所示,

re.sub(r"\s+", " ", re.search(r'/?q=([^&]*)', data['url'][i]).group(1).replace('+', ' ')

我想在pyspark中写相同的内容。

如果写的话,

 re.sub(r"\s+", " ", re.search(r'/?q=([^&]*)', data.select(data.url.alias("url")).collect()).group(1).replace('+', ' '))

re.sub(r"\s+", " ", re.search(r'/?q=([^&]*)', data.select(data['url']).collect()).group(1).replace('+', ' '))

我收到以下错误,

TypeError: expected string or buffer

一种选择是使用

将数据转换为pandas

data.toPandas()然后执行操作。但是我的数据非常庞大并将其转换为熊猫会让它变慢。有没有办法可以直接将它写入spark数据框中的新列,我可以这样做,

ID                URL                                                                           word
1             https://www.sitename.com/&q=To+Be+Parsed+out&oq=Dont+Need+to+be+parsed       To Be Parsed out   
2             https://www.sitename.com/&q=To+Be+Parsed+out&oq=Dont+Need+to+be+parsed       To Be Parsed out 
3             https://www.sitename.com/&q=To+Be+Parsed+out&oq=Dont+Need+to+be+parsed       To Be Parsed out 
4             https://www.sitename.com/&q=To+Be+Parsed+out&oq=Dont+Need+to+be+parsed       To Be Parsed out 
5             None                                                                             None

我们如何才能将其添加为pyspark数据帧中的新表?哪个适用于数据帧的每一行?

2 个答案:

答案 0 :(得分:0)

正如@David在评论中提到的那样,您可以使用udfwithColumn

Scala代码:

import org.apache.spark.sql.functions._

val getWord: (String => String) = (url: String) => {
  if (url != null) {
    """/?q=([^&]*)""".r
      .findFirstIn(url)
      .get
      .replaceAll("q=", "")
      .replaceAll("\\+", " ")
  }
  else
    null
}
val udfGetWord = udf(getWord)
df.withColumn("word", udfGetWord($"url")).show()

答案 1 :(得分:0)

Pyspark代码:

#Create dataframe with sample data

df = spark.createDataFrame([(1,'https://www.sitename.com/&q=To+Be+Parsed+out&oq=Dont+Need+to+be+parsed'),(2,'https://www.sitename.com/&q=To+Be+Parsed+out&oq=Dont+Need+to+be+parsed'),(3,'https://www.sitename.com/&q=To+Be+Parsed+out&oq=Dont+Need+to+be+parsed'),(4,'https://www.sitename.com/&q=To+Be+Parsed+out&oq=Dont+Need+to+be+parsed'),(5,'None')],['id','url'])

使用substr使用位置索引剪切所需的字符串,并使用instr标识搜索模式的位置。

regexp_replace用于将'+'符号替换为空格。

df.selectExpr("id",
              "url",
              "regexp_replace(substr(url,instr(url,'&q')+3, instr(url,'&oq') - instr(url,'&q') - 3 ),'\\\+',' ') AS word")\
.show()

#+---+--------------------+----------------+
#| id|                 url|            word|
#+---+--------------------+----------------+
#|  1|https://www.siten...|To Be Parsed out|
#|  2|https://www.siten...|To Be Parsed out|
#|  3|https://www.siten...|To Be Parsed out|
#|  4|https://www.siten...|To Be Parsed out|
#|  5|                None|                |
#+---+--------------------+----------------+

如果搜索字符串中不存在搜索模式,则将返回空白。可以使用case语句来处理。