Pyspark 最近使用的一些有趣姿势的梳理

之前对 SQL 还是不是非常熟悉的,但是现在或多或少还是会写一些计算任务。比如最近在推送将所有天级的耗时任务都从传统关系型数据库迁移至 Spark 集群当中进行计算,中间遇到一些有趣的小问题在这里记录一下。

Q: 我想按照某个字段分组并且把一组查询字段连起来得到一个 json 然后把结果作为一个字段应该怎么弄?

A: 这里我的思路是将我们需要 dumps 的字段给拼接起来,然后使用列表将同一个分组里面的是数据组合起来。然后过一个 udf 把列表中的记录处理成数组最后 json.dumps 一下即可。来看个栗子

# 先查询出要操作的目标信息 这一步可以和下面的操作合并,我这里为了方便看拆开了
df = ss.sql("""
                        SELECT
                            t1.pay_id,
                            t1.pay_money,
                            t1.user_id
                        FROM
                            analytics_db.hd_day_order_record t1
                    """)

# 拼接目标字符串并且组合
df = df.select(
               df.pay_id,
               df.pay_money,
               df.pay_user_id,
               f.concat_ws(‘\001‘, df.pay_id,  df.pay_user_id, df.pay_money).alias(‘sku_buys‘))
)

# 拼接一个重复 user_id 的 list
df = df.groupBy(df.pay_user_id).agg(f.collect_list(‘sku_buys‘).alias(‘sku_buys‘))

# 将 sku_buys 丢给一个 jsondump 的 udf 就可以得到结果了df = df.select(df.pay_user_id, sb_json(df.sku_buys).alias(‘sku_buys‘))

Q: 如果我想对目标进行分组,并且让他在组内有序应该怎么做?

A: 这通常被称为进行组内排序。其实我之前一直尝试用类似的语法来达到这种效果

df = ss.sql("""
        SELECT
            first(t1.sku_mode) AS sku_mode,
            first(t1.exchange_type_t01) AS exchange_type_t01,
            first(t1.user_id) AS user_id,
            first(t1.pay_id) AS pay_id,
            first(t1.charge_time) AS charge_time,
            first(t2.has_yxs_payment) AS has_yxs_payment,
            first(t2.has_sxy_payment) AS has_sxy_payment,
            first(t2.has_cxy_payment) AS has_cxy_payment,
            first(t2.has_sxy19_payment) AS has_sxy19_payment,
            first(t2.sxy19_join_time) AS sxy19_join_time,
            first(t2.yxs_join_time) AS yxs_join_time
        FROM
            d_exchange_info t1
        JOIN
            analytics_db.md_day_dump_users t2
        ON
            t2.the_day = ‘{}‘
            AND t1.user_id = t2.user_id
        GROUP BY
            t1.user_id
        ORDER BY
            charge_time
""".format(st))

其实这是错的,这里的 order by 并不能达到一个组内排序的效果,而是一个外部排序。所以这里取 first 是一个不稳定的结果。有时候你拿到的是一个结果,也许有时候你拿到的是另外一个结果。要进行组内排序,我们可以先用这样的思路,先对需要 order by 字段的表进行组内排序,然后再让他与其他表 join 获得更多的信息,这样就能保证是有序的。

这里我引用一个窗口函数来达到这样的效果。

        _df = ss.sql("""
                        SELECT
                            t1.user_id,
                            t1.pay_id,
                            t1.sku_mode,
                            t1.charge_time,
                            t1.exchange_type_t01,
                            ROW_NUMBER() OVER(PARTITION BY t1.user_id ORDER BY t1.charge_time)
                        FROM
                            {} t1
                        WHERE
                            t1.refund_state = 0
                    """.format(exchange_info_table))

我先使用窗口函数 ROW_NUMBER 以 user_id 分组并且根据 charge_time 对表一进行组内排序。得到结果之后,再与另外一张表 join 得到补充信息就能达到想要的效果。

Q: 我想对结果进行转列应该怎么做?

A: 行转列 列转行可能是 SQL 计算里面会经常使用到的方法,但是对于 SQL 并不熟悉的同学(比如我)就不知道该怎么整来看个例子

df = ss.sql("""
    SELECT
        user_id,
        sku_mode,
        credit_score
    FROM
        analytics_db.hd_day_user_credit
    WHERE
        gain_time >= ‘{}‘
        AND gain_time < ‘{}‘
        AND the_day = ‘{}‘
""".format(start_time, end_time, st))
# df.show(10)

展示的数据类似于

+--------------------+--------+------------+
|             user_id|sku_mode|credit_score|
+--------------------+--------+------------+
|d394899919216bc10...|     yxs|           3|
|625002ad625bc9a69...|     yxs|           3|
|8dd11e29bf50cb8c8...|     cxy|           3|
|0f0b88ff589cb46cd...|     yxs|           3|
|eeb8e839139876971...|     yxs|           1|
|f63b2b9c8340d3c80...|     cxy|           1|
|806c9f0349e7e8389...|     cxy|           1|
|bf312181eaaa0ec9e...|     yxs|           1|
|ee4a7984dc40cabbf...|     yxs|           3|
|7a6b15f16c1f782de...|   sxy19|           3|
+--------------------+--------+------------+
only showing top 10 rows

我们可以基于此将 sku_mode 一样的类型合并进行行转列变换

df = df.groupby(‘user_id‘).pivot(
    ‘sku_mode‘, [‘yxs‘, ‘cxy‘, ‘sxy‘, ‘sxy19‘]
).agg(
    f.sum(‘credit_score‘)
).fillna(0)

这句话的意思是根据 user_id 进行分组,并且将 sku_mode 的行转列,需要转列的类型需要在后面的 list 中添加,并且列里记录 各sku_mode credit_score 汇总的量。

+--------------------+---+---+---+-----+
|             user_id|yxs|cxy|sxy|sxy19|
+--------------------+---+---+---+-----+
|5ec336994e7b5d73f...|  0|  0|  0|    2|
|06b1120a4544b1b8a...|  0|  0|  0|    2|
|6fe19e193ad43bafc...|  0|  0|  0|    3|
|3e5f9fc4550ae7cba...|  1|  0|  0|    0|
|b1d1d856e28908f5a...|  1|  0|  0|    3|
|7a065e02ed1693cf4...|  2|  0|  0|    0|
|651f9f0b11de08003...|  0|  0|  0|    3|
|d02491502946aba2f...|  0|  0|  0|    2|
|e24b58cb87762b2da...|  0|  6|  0|   15|
|925f6a832b1a95c45...|  1|  0|  0|    0|
+--------------------+---+---+---+-----+
only showing top 10 rows

原文地址:https://www.cnblogs.com/piperck/p/10917368.html

时间: 2024-10-10 21:37:01

Pyspark 最近使用的一些有趣姿势的梳理的相关文章

【BZOJ-4127】Abs 树链剖分 + 线段树 (有趣的姿势)

4127: Abs Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 381  Solved: 132[Submit][Status][Discuss] Description 给定一棵树,设计数据结构支持以下操作 1 u   v d 表示将路径 (u,v) 加d 2 u v 表示询问路径 (u,v) 上点权绝对值的和 Input 第一行两个整数n和m,表示结点个数和操作数 接下来一行n个整数a_i,表示点i的权值 接下来n-1行,每行两个整数u,v

机器学习原来如此有趣:用深度学习识别人脸

本系列文章目前已经更新两期,分别是: 机器学习原来如此有趣!全世界最简单的机器学习入门指南. 机器学习原来如此有趣:如何故意欺骗神经网络 你是否有注意到Facebook最近开发了一个非同寻常的功能:将你照片中的好友识别出来.过去,Facebook 让你手动点击照片上的好友,输入他们的名字,然后加上标签.现在只要你上传一张照片,Facebook就会像变魔术一样为你自动标记出所有人: 这项技术就叫做人脸识别.在你的朋友的脸被标记了几次之后,Facebook的算法就可以识别他了.这是一个让人惊艳的技术

设计安全的账号系统的正确姿势【转】

引子 最近有个虚拟练习项目,涉及到系统安全保障的设计,于是对安全保障这块做了一些更深入的了解.发现了很多有趣的东西,开阔了眼界.中间查了一些资料,于是我打算重新整理,用更加循序渐进,大家都能懂的方式,说一说如何设计一个安全的系统. 著名的安全事件 首先来看看最近几年比较著名的拖库撞库后密码泄露的事件: 2011年12月,国内最大的程序员社区 CSDN 遭拖库,600万个账户信息泄露. 2014年3月,携程旅行网的系统存技术漏洞,漏洞可能导致用户的姓名.身份证号码.银行卡类别.银行卡卡号.银行卡C

使用layoutinflater的正确姿势

使用layoutinflater的正确姿势 一开始接触安卓开发的时候,知道layoutinflater是用来将布局文件生成对应的View.那时候还是懵懵懂懂知道需要传递一个layoutId一个parent参数和一个false参数.那时候就这样用,初初还是好好的.直到后来随着进一步学习安卓开发发现layoutinflater的这两个参数是有大大的门道在里面. 然后这一篇博客可以说是我对layoutinflater使用的一个总结. 怎么添加一个View到ViewGroup? 在讨论怎么使用layou

(转) exp1:// 一次有趣的XSS漏洞挖掘分析(1)

from http://www.cnblogs.com/hookjoy/p/3503786.html 一次有趣的XSS漏洞挖掘分析(1) 最近认识了个新朋友,天天找我搞XSS.搞了三天,感觉这一套程序还是很有意思的.因为是过去式的文章,所以没有图.但是希望把经验分享出来,可以帮到和我一样爱好XSS的朋友.我个人偏爱富文本XSS,因为很有趣.有趣的地方是你需要一点一点的测试都过滤了些什么,怎么过滤的.我想,这也是黑盒测试最让人着迷的地方吧    首先,锁定了提交问题的模块,因为这块有编辑器.然后开

设计安全的账号系统的正确姿势

引子 最近有个虚拟练习项目,涉及到系统安全保障的设计,于是对安全保障这块做了一些更深入的了解.发现了很多有趣的东西,开阔了眼界.中间查了一些资料,于是我打算重新整理,用更加循序渐进,大家都能懂的方式,说一说如何设计一个安全的系统. 著名的安全事件 首先来看看最近几年比较著名的拖库撞库后密码泄露的事件: 2011年12月,国内最大的程序员社区 CSDN 遭拖库,600万个账户信息泄露. 2014年3月,携程旅行网的系统存技术漏洞,漏洞可能导致用户的姓名.身份证号码.银行卡类别.银行卡卡号.银行卡C

3星|《高能量姿势》:主动采取强势的姿势可以提高自信和工作学习表现

前半部分讲大部分人都有“冒名顶替综合征”,或者说冒充者恐惧心理,表现形式是对自己不自信,总觉得自己是冒充了一个更优秀的人,总是害怕被人揭穿. 后半部分提出高能量姿势和低能量姿势,高能量姿势就是让人显得更强势的姿势,具体表现在不同文化中可能不同.作者认为:高能量姿势可以让人更自信,工作和学习更积极主动效果更好,身体更健康,所有人都可以尝试高能量姿势,对缓解冒名顶替综合征可以有很好的效果. 作者的高能量姿势的效果,证据来自一些实验室内的小型心理学实验和许多个案.作为畅销书来说,这些证据也说得过去了.

SpringBoot 开发案例之参数传递的正确姿势

前言 开发这么多年,肯定还有不少小伙伴搞不清各种类型的参数是如何传递的,很多同学都是拿来即用,复制粘贴一把撸,遇到问题还是一脸懵逼. 姿势 学习参数传递的正确姿势,先说怎么做,再说为什么,本质上还是复制粘贴一把撸,问题是你想问不想问为什么! 传递 用户登录 前端代码: var param = { "username": "admin", "password": "admin" } $.ajax({ url: "/sy

羞,Java 字符串拼接竟然有这么多姿势

二哥,我今年大二,看你分享的<阿里巴巴 Java 开发手册>上有一段内容说:"循环体内,拼接字符串最好使用 StringBuilder 的 append 方法,而不是 + 号操作符."到底为什么啊,我平常一直就用的'+'号操作符啊!二哥有空的时候能否写一篇文章分析一下呢? 就在昨天,一位叫小菜的读者微信我说了上面这段话. 我当时看到这条微信的第一感觉是:小菜你也太菜了吧,这都不知道为啥啊!我估计正在读这篇文章的你也会有同样的感觉. 但扪心自问,在我做程序员的前两年内,我也不