pyspark:dataframe使用pandas_udf做groupby

 

目录

 

带多参数实现:

主要知识点链接:


带多参数实现:

pypsark的dataframe经常遇到要做groupby的场景,有两种方式可以实现,dataframe的pandas_udf、rdd的mapValues,后者需要先将dataframe转换成rdd再操作

下面介绍dataframe的pandas_udf代码实现,由于pandas_udf做groupby传入参数只能是函数名,不能传入其他参数

@pandas_udf(schema1, functionType=PandasUDFType.GROUPED_MAP)
def ftscore2(df):
    print('ok')
    mid = df.groupby(['device_number']).apply(lambda x: ftScore(x))
    print("mid",mid)
    result = pd.DataFrame(mid)
    return result
aa = ldf2.groupby(['device_number']).apply(ftscore2)
aa.show()


所以想传入参数需要再里面再嵌套一个python函数

def flow_sum_app(df4):
    rst=np.sum(df4[["total_flow"]])[0]
    return rst
fcls = [flow_sum_app]
cmls=[]
appls=['金融理财','商务办公','旅游出行','网上购物','小额借贷','财经资讯','头部银行','地方银行','商业银行']
fcls1 = ["flow_sum_app"]
for i in appls:
    for f1 in fcls1:
        cmls.append(i+"_"+f1)
schema3 = StructType([
    StructField("device_number", StringType()),
])
for i in cmls:
    schema3.add(i,DoubleType(), True)
print(schema3)
 
 
 
 
def ft7(df3,appls,fcls,fcls1):
    rsls=[df3['device_number'].iloc[0]]
    for i in appls:
        df4=df3[df3.prod_label_name3==i]
        for f in fcls:
            rsls.append(f(df4))
    cmls=["device_number"]
    for i in appls:
        
        for f1 in fcls1:
            cmls.append(i+"_"+f1)
    df5= pd.DataFrame(data=[rsls],columns=cmls)
#     print("df5",df5)
    return df5
@pandas_udf(schema3, functionType=PandasUDFType.GROUPED_MAP)
def ftscore6(df3):
    
    return ft7(df3,lb1,fcls,fcls1)
 
from pyspark.sql.functions import pandas_udf,PandasUDFType
 
ldf2 = spark.createDataFrame(
[("a", '金融理财',11), ("a", '小额借贷',12), ("b", '小额借贷',8), ("b", '旅游出行',10)],
("device_number", "prod_label_name3","total_flow"))
aa = ldf2.groupby(['device_number']).apply(ftscore6)
aa.show()
————————————————

原文链接:https://blog.csdn.net/sisiel/article/details/105455230

解读:

ftscore6 是个pandas_udf函数,接受pyspark 的dataframe,接收进来按照pandas的dataframe处理,但这个dataframe是带着key(device_number)的dataframe(此时由于groupby了,所以key都是一样的),不能接受其他参数

ft7是个纯python函数,接收pandas dataframe,可以接收其他参数
————————————————
版权声明:本文为CSDN博主「sisiel」的原创文章

主要知识点链接:

https://www.cnblogs.com/wonglu/p/7784825.html

 

groupby  apply实例:

sum和udf方法计算平均得分
数据介绍:主播表,一个主播有很多直播课,每个直播课都有一个总评分和评分人数,现要计算出该主播的平均得分。

思路:单个主播的所有的直播课的分数全部加起来,除以所有直播课的共同的评分人数。

from pyspark.sql.types import DoubleType
from pyspark.sql.functions import udf
def Spark():
	"""
	spark配置类
	"""
sp = Spark()
spark = sp.spark

df = spark.sql("select anchor_id,live_score,live_comment_count from table_anchor")
df = df.groupBy('anchor_id')
	   .agg({"live_score": "sum", "live_comment_count": "sum"})
	   .withColumnRenamed("sum(live_score)", "total_score")
	   .withColumnRenamed("sum(live_comment_count)", "total_people")


现在就获得了两列 总分数和总人数
使用udf方法自定义函数即可求的平均分

def avg_score(score,people):
	try:
		if int(people) != 0:
			return int(score)/int(people)
		else:
		return 0
	except:
		return 0
	
func = udf(avg_score,DoubleType())
df = df.withColumn("score", func(df.total_score,df.total_people))
df = df.select("anchor_id","score")  # 选择ID和分数两列即可存表


avg方法计算平均得分
数据介绍:有一个课程评分的记录表,表项为课程ID,用户ID,该用户对课程的评分,现计算该课程的平均评分

思路:使用 avg方法直接计算。

df = spark.sql("select course_id,score from table_course")
df = df.groupBy("course_id")
       .agg({"score": "avg"})
       .withColumnRenamed("avg(score)", "avg_score")
df = df.select("course_id","avg_score")


获取course_id 和avg_score 之后即可存表 注:spark为上一节中spark

count方法计算资源个数
数据介绍:有一个课程评分的记录表,表项为课程ID,用户ID,该用户对课程的评论,现计算该课程有多少人评论

df = spark.sql("select course_id,comment from table_course")
df = df.groupBy("course_id")
       .agg({"comment": "count"})
       .withColumnRenamed("count(comment)", "comment_count")
df = df.select("course_id","comment_count")

 
获取course_id 和comment_count 之后即可存表 注:spark为第一节中spark

collect_list() 将groupBy 的数据处理成列表
数据介绍:有一个课程评分的记录表,表项为课程ID,用户ID,该用户对课程的评论,现将用户评论放在列表中,便于后续处理

from pyspark.sql.functions import collect_list
df = spark.sql("select course_id,comment from table_course")
df = df.groupBy("course_id")
       .agg(collect_list("comment"))
       .withColumnRenamed("collect_list(comment)", "comment_list")
df = df.select("course_id","comment_list")


获取course_id 和comment_list 之后即可存表,或者对comment_list使用udf自定义函数,将数据组拼接成字符串。 注:spark为第一节中spark, 注意import包

max取最大值min取最小值
数据介绍:供应商发布课程表,供应商发布了很多课程,发布的每个课程都有发布时间,在数据库中是timestamp类型,数据表中表项为org_id, course_id, publish_date,现要获取供应商发布课程的最新时间作为该供应商的最新活跃时间。

思路:timestamp类型的数据也可使用max

df = spark.sql("select org_id,course_id,publish_date from org_table")
df = df.groupBy("org_id")
       .agg({"publish_date": "max"})
       .withColumnRenamed("max(publish_date)", "active_time")
df = df.select("org_id","active_time")

 
获取org_id 和active_time 之后即可存表。 注:spark为第一节中spark

多条件groupBy求和sum
数据介绍:一张企业表,企业下有很多职位,不同的企业可能有相同的职位,基于每个企业下的每个职位,统计了该职位某个热搜词被检索的次数,现需要根据职位类别统计各个热搜词被检索的总次数。

企业ID    职位ID    热搜词    该热搜词被检索次数
org_id    pos_id    word    word_count
A1    pos001    保险金融    1
A1    pos002    保险金融    2
A1    pos003    保险金融    3
A1    pos004    保险金融    4
A2    pos001    保险金融    5
A2    pos001    教育    6
A2    pos003    保险金融    7
A2    pos003    智能    8
思路:

df = spark.sql("select pos_id,word,word_count from org_table")
df = df.groupBy("pos_id","word")
       .agg({"word_count": "sum"})
       .withColumnRenamed("sum(word_count)", "total_count")
df = df.select("pos_id","word","total_count")


根据职位类别ID和热搜词两个条件聚合数据,将相同职位ID和相同热搜词的表项聚合在一起,将聚合在一起的词频累加。 注:spark为第一节中spark

结果:

职位ID    热搜词    该热搜词被检索次数
pos_id    word    word_count
pos001    保险金融    6
pos002    保险金融    2
pos003    保险金融    10
pos004    保险金融    4
pos001    教育    6
pos003    智能    8
此时如若需要对某个职位下的所有的热搜词按频率排序,然后只保留top5,则后续工作可以使用udf自定义函数的方法,将词和词频整合成字典或者列表,然后按照pos_id聚合再一起,用sorted按词频排序。

原文链接:https://blog.csdn.net/weixin_42864239/article/details/94456765

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
pandas_udfPySpark中的一个API,用于定义用户自定义函数(User Defined Functions,简称UDFs)。它使用Arrow传输数据并使用Pandas进行数据处理,可以进行向量化操作。有两种类型的pandas_udf,分别是Scalar(标量映射)和Grouped Map(分组映射)。 Scalar Pandas UDF用于向量化标量操作,常常与select和withColumn等函数一起使用。调用的Python函数需要使用pandas.Series作为输入并返回一个具有相同长度的pandas.Series。具体执行流程是,Spark将列分成批,并将每个批作为数据的子集进行函数的调用,进而执行Pandas UDF,最后将结果连接在一起。 Grouped Map Pandas UDF用于在分组的数据上进行向量化操作。它可以在GroupBy操作后的DataFrame使用,相比于Scalar Pandas UDF,它可以处理更复杂的逻辑,例如聚合操作。使用Grouped Map Pandas UDF时,需要使用@pandas_udf装饰器或包装函数来定义函数。 通过使用pandas_udf,可以更高效地处理数据,提高数据处理的效率和性能。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [pyspark pandas_udf](https://blog.csdn.net/weixin_40161254/article/details/91548469)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [一文解读pandas_udf](https://blog.csdn.net/weixin_42223090/article/details/130126261)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值