目录
一、udf函数的使用基础
方式1:用@装饰器注册udf函数
方法2: 注册udf函数
二、udf函数传入多个参数
三、udf函数传入固定参数/常数值/string
方法1:利用 lit()函数
方法2:利用闭包
方法3:利用lambda匿名函数+闭包
四、传入字典/tuple等特殊数据类型
五、传出多个参数
六、参考文献
特点:注册为udf函数的函数不能直接再被其他地方调用,使用不方便,我个人不建议这种形式
from pyspark.sql.functions import udf
from pyspark.sql.types import StringType
import numpy as np
import math
@udf(returnType=StringType())
def caculateClusterBelongTo(inlist):
try:
#不用再进行for line in sys.stdin
#直接对数据执行split,因为进来的就只有一行数据
thing1,thing2,thing3,thing4 = inlist.strip().decode('utf-8').split('&&')
…….. #省略中间过程
out= '$$'.join([str(thing1),str(currentShortestDistance),str(thisPoiCurrentCluster)])
return out
except Exception,e:
return 'wrong'
pass
特点: 可以单独注册一个新的udf函数,个人认为可以起一个别的名字,方便识别,又不与之前的函数冲突,方便各自独立使用
def func(data_col1):
xxxx #进行处理
return str_out
func_udf = udf( func, StringType())
# 以下两者读取 col 列数据的方式不同 都可以用效果一样
# 1
df_out = df.withColumn("new_col", func_udf(df["col1"]))
# 2
df_out = df.withColumn("new_col", func_udf(df.col1))
def func(data_col1,data_col2):
xxxx #进行处理
return str_out
func_udf = udf( func, StringType())
# 以下两者读取 col 列数据的方式不同 都可以用效果一样
# 1
df_out = df.withColumn("new_col", func_udf(df["col1"],df["col2"]))
# 2
df_out = df.withColumn("new_col", func_udf(df.col1,df.col2))
用pyspark的lit函数,df增加一列每一行都为固定参数的列
再将多列传入普通的udf函数中
def func(col_var,businesstype, routeid, locale, languagetype, sentence):
# 可以执行一些操作
xyz = func_other(col_var,businesstype, routeid, locale, languagetype, sentence)
return xyz
func_udf = udf( func, StringType())
# 先增加一列值为var的列 每一行数据都一样是var
df = df.withColumn('col_var', F.lit(var))
# 再执行主要的计算步骤
df_out = df.withColumn("new_col", func_udf(df.businesstype, df.businessid, df.locale,df.languagetype, df.content, df.col_var)
函数套函数
def generate_udf(var1, var2):
def func_inudf(businesstype, routeid, locale, languagetype, sentence):
# func_inudf中可以将外部的固定变量当做全局变量使用
var1_ = f1(var1)
var2_ = f2(var2)
# 也可以增加一些其他的操作
xyz = f3(businesstype, routeid, locale, languagetype, sentence)
return xyz
return F.udf(func_inudf, StringType())
df_out = df.withColumn('new_col',
generate_udf(var1, var2)(df.businesstype, df.businessid, df.locale,df.languagetype, df.content)
# df_out会增加一列叫new_col的,返回值是xyz
外部调用udf时输入的列和内部的匿名函数的参数位置对应,
输入的固定参数和内部的大函数参数位置对应
内部的匿名函数可以使用内部的大函数的参数,从而保证内部函数的参数完整
# 功能:grid search
def NDCG_sort_process(weight):
return udf(lambda expo,click:NDCG_sort(expo,click,weight))
def top_sort_process(weight):
return udf(lambda expo,click:top_ratio_sort(expo,click,weight))
from tqdm import tqdm
for i in tqdm(range(1,100,)):
info_sort=info_top.withColumn("NDCG_sort",NDCG_sort_process(0.1*i)(info_top.expo,info_top.click))
info_top_sort=info_sort.withColumn("top_ratio_sort",top_sort_process(0.1*i)(info_sort.expo,info_sort.click))
print("weight:%f NDCG:%f" % (0.1*i,info_top_sort.agg({"NDCG_sort": "avg"}).toPandas()['avg(NDCG_sort)'].tolist()[0]))
print("weight:%f top10 ratio:%f" % (0.1*i,info_top_sort.agg({"top_ratio_sort": "avg"}).toPandas()['avg(top_ratio_sort)'].tolist()[0]))
利用json序列化一下数据,传参,使用的时候再解析
def generate_udf(json_dict, var1, var2):
def func_inudf(businesstype, routeid, locale, languagetype, sentence):
# func_inudf中可以将外部的固定变量当做全局变量使用
# 内部函数中对其重新解析为字典使用
dict_ = json.loads(json_dict)
var1_ = f1(var1)
var2_ = f2(var2)
# 也可以增加一些其他的操作
xyz = f3(dict_, businesstype, routeid, locale, languagetype, sentence)
return xyz
return F.udf(func_inudf, StringType())
# 利用json序列化一下数据,传参,使用的时候再解析
json_dict = json.dumps( dict_ )
df_out = df.withColumn('new_col',
generate_udf(json_dict, var1, var2)(df.businesstype, df.businessid, df.locale,df.languagetype, df.content)
# df_out会增加一列叫new_col的,返回值是xyz
将需要输出的固化为json或者字符串,用特殊符号作为分隔符将其相连
输出后再根据特殊符号的分隔符将其split开
再取对应位置的参数到新的列
def generate_udf(json_dict, var1, var2):
def func_inudf(businesstype, routeid, locale, languagetype, sentence):
# func_inudf中可以将外部的固定变量当做全局变量使用
# 内部函数中对其重新解析为字典使用
dict_ = json.loads(json_dict)
var1_ = f1(var1)
var2_ = f2(var2)
# 也可以增加一些其他的操作
x, y, z = f3(dict_, businesstype, routeid, locale, languagetype, sentence)
return x+"@@"+y +"@@"+ z
return F.udf(func_inudf, StringType())
# 利用json序列化一下数据,传参,使用的时候再解析
json_dict = json.dumps( dict_ )
df_out = df.withColumn('new_col',
generate_udf(json_dict, var1, var2)(df.businesstype, df.businessid, df.locale,df.languagetype, df.content)
# df_out会增加一列叫new_col的,返回值是xyz
df_split = df_out.withColumn("s", F.split(df1['new_col'], "@@"))
df_split = df_split.withColumn('Item0', df_split["s"].getItem(0))
df_split = df_split.withColumn('Item1', df_split["s"].getItem(1))
df_split = df_split.withColumn('Item2', df_split["s"].getItem(2))
df_out_final = df_split
【Pyspark】 一列变多列 、分割 一行中的list分割转为多列 explode,多列变一列(可保持原顺序), 多行变一行
https://blog.csdn.net/sunflower_sara/article/details/104044252
pySpark udf函数传入常数值
https://www.pythonheidong.com/blog/article/275097/
pyspark中udf传参数(非列值参数)
https://blog.csdn.net/u011582757/article/details/102991347?depth_1-utm_source=distribute.pc_relevant.none-task&utm_source=distribute.pc_relevant.none-task
Spark UDF使用详解及代码示例
https://www.jianshu.com/p/bded081b5350