Pyspark Pandas-Vectorized UDF

nfeuvbwi  于 2023-05-16  发布在  Spark
关注(0)|答案(1)|浏览(117)

为了避免创建两个pandas udf,我正在尝试将这个udf转换为这个pandas udf。
转换这个:

@udf("string")
  def splitEmailUDF(email: str, position: int) -> str:
  return email.split("@")[position]

在一个Pandas的udf ---位置???数据类型或其他东西!

from pyspark.sql.functions import pandas_udf, PandasUDFType
    
@pandas_udf("string")
def splitEmailUDFVec(email: pd.Series, position: ???????) -> pd.Series:
  return email.str.split("@").str[position]

当然,我总是可以创建两个pandas_udfs:

from pyspark.sql.functions import pandas_udf
        
@pandas_udf("string")
def splitFirstNameUDFVec(email: pd.Series) -> pd.Series:
  return email.str.split("@").str[0]
        
@pandas_udf("string")
def splitDomainUDFVec(email: pd.Series) -> pd.Series:
  return email.str.split("@").str[1]

任何帮助将不胜感激!

ruarlubt

ruarlubt1#

设置

df.show()

+------------+
|       email|
+------------+
| foo@bar.com|
|baz@spam.com|
+------------+

定义一个 Package 器函数,它以email和pos作为参数,并返回底层的pandas udf函数

def split(email, pos):
    @F.pandas_udf('string')
    def _split(email: pd.Series) -> pd.Series:
        return email.str.split('@').str[pos]
    
    return _split(email)

df = df.withColumn('firstname', split('email', 1))

结果

df.show()

+------------+--------+
|       email|  domain|
+------------+--------+
| foo@bar.com| bar.com|
|baz@spam.com|spam.com|
+------------+--------+

如果您的目标是只将电子邮件地址拆分为其名称和域组件,那么另一种更好/更有效的方法是使用正则表达式提取。

f = lambda n: F.regexp_extract('email', '(.*)@(.*)', n)
df = df.select('*', f(1).alias('firstname'), f(2).alias('domain'))

结果

df.show()

+------------+---------+--------+
|       email|firstname|  domain|
+------------+---------+--------+
| foo@bar.com|      foo| bar.com|
|baz@spam.com|      baz|spam.com|
+------------+---------+--------+

相关问题