如何从 PySpark DataFrame 的列中分离特定字符并使用它们形成一个新列?

Posted

技术标签:

【中文标题】如何从 PySpark DataFrame 的列中分离特定字符并使用它们形成一个新列?【英文标题】:How to separate specific chars from a column of a PySpark DataFrame and form a new column using them? 【发布时间】:2020-11-05 15:41:34 【问题描述】:

我对 PySpark 非常陌生,我真的很难理解如何使用它。我有一个案例,我必须对仅包含 column1 的 PySpark DataFrame 应用操作,如下所示,并返回一个包含 column1、column2 和 column3 的新数据帧:

column1              column2      column3
'A123'                '123'         'A'
'321B'   --------->   '321'         'B'
'C875'                '875'         'C'

要分隔的字符是 ['A', 'B', 'C'] 并且它们可以在 'column1' 中的字符串的前面或末尾。 column1 中的每个字符串都有一个,而且只有一个。

【问题讨论】:

您可以使用 udf 解决此问题。两个udf。一个将允许您提取字符串。第二个将允许您仅提取整数。 sparkbyexamples.com/pyspark/pyspark-udf-user-defined-function 【参考方案1】:

您可以使用 UDF 来执行此操作。或者你可以使用内置的regex_extract函数来提取

from pyspark.sql import Row
from pyspark.sql.types import *
from pyspark import SparkContext, SQLContext
from pyspark.sql.functions import *

sc = SparkContext('local')
sqlContext = SQLContext(sc)

data1 = [
    ('A123',),
    ('321B',),
    ('C875',) ,
      ]


df1Columns = ["column1"]
df1 = sqlContext.createDataFrame(data=data1, schema = df1Columns)
df1.show(20, truncate=False)


import re

def findChar(input_string):
    result = "".join(re.findall("[A-C]", input_string))
    return result

findChar_udf = udf(findChar, StringType())

def findNumber(input_string):
    result = "".join(re.findall("[0-9]+", input_string))
    return result

findNumber_udf = udf(findNumber, StringType())

print("Using udf")
df2 = df1.withColumn("column2", findChar_udf("column1")).withColumn("column3", findNumber_udf("column1"))
df2.show(20, truncate=False)

print("Using regex_extract")
df3 = df1.withColumn("column2", regexp_extract("column1", "[A-C]", 0)).withColumn("column3", regexp_extract("column1", "[0-9]+", 0))
df3.show(20, truncate=False)

以下是输出:

+-------+
|column1|
+-------+
|A123   |
|321B   |
|C875   |
+-------+

Using udf
+-------+-------+-------+
|column1|column2|column3|
+-------+-------+-------+
|A123   |A      |123    |
|321B   |B      |321    |
|C875   |C      |875    |
+-------+-------+-------+

Using regex_extract
+-------+-------+-------+
|column1|column2|column3|
+-------+-------+-------+
|A123   |A      |123    |
|321B   |B      |321    |
|C875   |C      |875    |
+-------+-------+-------+

【讨论】:

【参考方案2】:

您可以使用正则表达式来分隔两个条件并获取子字符串。

import pyspark.sql.functions as F

df.select('column1', 

F.when(
    F.col('column1').rlike('^[ABC]'), 
    F.substring(F.col('column1'), 2, 3)
).when(
    F.col('column1').rlike('[ABC]$'),
    F.substring(F.col('column1'), 1, 3)
).alias('column2'),

F.when(
    F.col('column1').rlike('^[ABC]'), 
    F.substring(F.col('column1'), 1, 1)
).when(
    F.col('column1').rlike('[ABC]$'),
    F.substring(F.col('column1'), 4, 1)
).alias('column3')

)

【讨论】:

以上是关于如何从 PySpark DataFrame 的列中分离特定字符并使用它们形成一个新列?的主要内容,如果未能解决你的问题,请参考以下文章

如何从 PySpark DataFrame 的列中分离特定字符并使用它们形成一个新列?

Pyspark - 如何将转换后的列与原始 DataFrame 合并?

从 pandas DataFrame 中的列中提取 JSON 数据

如何将日期转换为 PySpark Dataframe 列中的第一天?

从 pyspark 数据框中的列中提取特定字符串

如何在 PySpark 中的 RDD 中的列中查找标准差