PySpark SQL常用语法

from https://www.jianshu.com/p/177cbcb1cb6f

  • PySpark的语法是从左到右串行的,便于阅读、理解和修正;SQL的语法是从内到外嵌套的,不方便维护;
  • PySpark继承Python优美、简洁的语法,同样的效果,代码行数可能只有SQL的十分之一;
  • Spark分转化操作和行动操作,只在行动操作时才真正计算,所以可以减少不必要的计算时间;
  • 相对于SQL层层嵌套的一个整体,PySpark可以拆分成多步,并可以十分方便地把中间结果保存为变量,更有利于调试和修改;
  • PySpark可以与Python中的其他模块结合使用,可以将多种功能有机结合成一个系统
  • PySpark SQL模块许多函数、方法与SQL中关键字一样,可以以比较低的学习成本切换
  • 最重要的,Spark是基于内存计算的,计算速度本身比Hive快很多倍

PySpark的安装配置

如果只是在单机上练习下,照着网上的帖子在Linux系统安装一下就可以了;如果想真正在集群上实战,还是找运维搭建吧。

PySpark SQL语法

最好的学习资料当然是官方文档,不过官方文档是按函数名排序的,这对于新手不太友好,所以这里整理一下。

数据拉取

第一步是拉取数据,与SQL、Pandas、R一样,在SparkSQL中,我们以DataFrame以基本的数据结构(不过要注意,SparkSQL DataFrame与Pandas的DataFrame是两种数据结构,虽然相互转换也很容易)。

加载包
from __future__ import print_function
import pandas as pd
from pyspark.sql import HiveContext
from pyspark import SparkContext,SparkConf
from sqlalchemy import create_engine
import datetime
import pyspark.sql.functions as F

conf = SparkConf().setAppName(“abc”)
sc = SparkContext(conf=conf)
hiveCtx = HiveContext(sc)


手工创建一个DataFrame
d = [{'name': 'Alice', 'age': 1},{'name': 'Bob', 'age': 5}]
df = sqlContext.createDataFrame(d)
df.show() 
从集群里运行SQL生成DataFrame

实际工作中往往是从集群中拉数,然后处理;还是执行SQL(尽管仍是SQL,但是不必写复杂的SQL;用基本的SQL先把源数据拉出来,复杂的处理和计算交给Spark来做),以下是用Hive拉数:

sql = "" # 拉数SQL
df  = hiveCtx.sql(sql)

缓存与清除缓存

Spark每次作行动操作时,都是从最初的转化操作开始计算;如果不想从头开始计算,想保存中间结果表,就应该把数据载入缓存。

df.cache()

与之相对的,清除缓存为

sqlContext.clearCache()

数据探索
展示
df.show() # 不加参数默认展示前20行
统计行数
df.count() 
查看schema
df.printSchema() 
查看字段
df.columns
查看字段类型
df.dtypes

数据处理
查询
df.select('age','name') # 带show才能看到结果
别名
df.select(df.age.alias('age_value'),'name')
筛选
df.filter(df.name=='Alice')
增加列

增加列有2种方法,一种是基于现在的列计算;一种是用pyspark.sql.functions的lit()增加常数列。

df.select(df.age+1,'age','name')
df.select(F.lit(0).alias('id'),'age','name')
增加行
df.unionAll(df2)
删除重复记录
df.drop_duplicates()
去重
df.distinct()
删除列
df.drop('id')
删除存在缺失值的记录
df.dropna(subset=['age', 'name'])  # 传入一个list,删除指定字段中存在缺失的记录
填补缺失值
df.fillna({'age':10,'name':'abc'})  # 传一个dict进去,对指定的字段填充
分组计算
df.groupby('name').agg(F.max(df['age']))
join
df.groupby('name').agg(F.max(df['age']))

函数和UDF

pyspark.sql.functions里有许多常用的函数,可以满足日常绝大多数的数据处理需求;当然也支持自己写的UDF,直接拿来用。

自带函数

根据官方文档,以下是部分函数说明:

'lit': 'Creates a :class:`Column` of literal value.',
'col': 'Returns a :class:`Column` based on the given column name.',
'column': 'Returns a :class:`Column` based on the given column name.',
'asc': 'Returns a sort expression based on the ascending order of the given column name.',
'desc': 'Returns a sort expression based on the descending order of the given column name.',

‘upper’: ‘Converts a string expression to upper case.’,
‘lower’: ‘Converts a string expression to upper case.’,
‘sqrt’: ‘Computes the square root of the specified float value.’,
‘abs’: ‘Computes the absolutle value.’,

‘max’: ‘Aggregate function: returns the maximum value of the expression in a group.’,
‘min’: ‘Aggregate function: returns the minimum value of the expression in a group.’,
‘first’: ‘Aggregate function: returns the first value in a group.’,
‘last’: ‘Aggregate function: returns the last value in a group.’,
‘count’: ‘Aggregate function: returns the number of items in a group.’,
‘sum’: ‘Aggregate function: returns the sum of all values in the expression.’,
‘avg’: ‘Aggregate function: returns the average of the values in a group.’,
‘mean’: ‘Aggregate function: returns the average of the values in a group.’,
‘sumDistinct’: ‘Aggregate function: returns the sum of distinct values in the expression.’,

df.select(F.max(df.age))
df.select(F.min(df.age))
df.select(F.avg(df.age)) # 也可以用mean,一样的效果
df.select(F.countDistinct(df.age)) # 去重后统计
df.select(F.count(df.age)) # 直接统计,经试验,这个函数会去掉缺失值会再统计

from pyspark.sql import Window
df.withColumn("row_number", F.row_number().over(Window.partitionBy("a","b","c","d").orderBy("time"))).show() # row_number()函数

日期相关函数参考:pyspark系列--日期函数

UDF

统计计算
描述性统计分析
df.describe('age').show() # describe()相当于R里的summary()

数据写出

数据写出有以下几种情况——

  • 写入集群分区表
all_bike.rdd.map(lambda line: u','.join(map(lambda x:unicode(x),line))).saveAsTextFile('/user/hive/warehouse/bi.db/bikeid_without_3codes_a_d/dt={}'.format(t0_uf)) #转化为RDD写入HDFS路径

还有一种方法,是先把dataframe创建成一个临时表,再用hive sql的语句写入表的分区。

bike_change_2days.registerTempTable('bike_change_2days')
sqlContext.sql("insert into bi.bike_changes_2days_a_d partition(dt='%s') select citycode,biketype,detain_bike_flag,bike_tag_onday,bike_tag_yesterday,bike_num from bike_change_2days"%(date))
  • 写入集群非分区表
df_spark.write.mode("append").insertInto('bi.pesudo_bike_white_list') # 直接使用write.mode方法insert到指定的集群表
  • 写入数据库
    可以先将PySpark DataFrame转化成Pandas DataFrame,然后用pandas的to_sql方法插入数据库

  • 写出本地

df.write.csv()

与Pandas DataFrame互相转换

如果你熟悉Pandas包,并且PySpark处理的中间数据量不是太大,那么可以直接转换成pandas DataFrame,然后转化成常规操作。

df.toPandas() # PySpark DataFrame转化成Pandas DataFrame
import pandas as pd
df_p = pd.DataFrame(dict(num=range(3),char=['a','b','c']))
df_s = sqlContext.createDataFrame(df_p) # pandas dataframe转化成PySpark DataFrame
type(df_s)
机器学习

关于机器学习,在以后的文章里再单独讨论。

      </div>
    </div>
</div>

<!-- 如果是付费文章,未购买,则显示购买按钮 -->

<!-- 连载目录项 -->

<!-- 如果是付费文章 -->
  <!-- 如果是付费连载,已购买,且作者允许赞赏,则显示付费信息和赞赏 -->
    <div id="free-reward-panel" class="support-author"><p>写作劳动有价,知识分享无价~</p> <div class="btn btn-pay">赞赏支持</div> <div class="supporter"><ul class="support-list"><li><a target="_blank" href="/u/d80735295ca7" class="avatar"><img src="//upload.jianshu.io/users/upload_avatars/8428973/3f421941-e140-4715-a7c0-bd4a3972fcf7?imageMogr2/auto-orient/strip|imageView2/1/w/40/h/40/format/webp"></a></li></ul> <!----></div> <!----> <!----></div>

  <div class="show-foot">
    <a class="notebook" href="/nb/24270353">
      <i class="iconfont ic-search-notebook"></i>
      <span>数据科学</span>



  <!-- 文章底部作者信息 -->
    <div class="follow-detail">
      <div class="info">
        <a class="avatar" href="/u/fc7499020f49">
          <img src="//upload.jianshu.io/users/upload_avatars/1932359/f25b33a61fce?imageMogr2/auto-orient/strip|imageView2/1/w/96/h/96" alt="96">


真依然很拉风

写了 59756 字,被 425 人关注,获得了 518 个喜欢


我一个字不写,那是坠吼的。
但是看到你们这么热情,
我一个字不写也不好。

<div class="meta-bottom">
  <div data-v-6ddd02c6="" class="like"><div data-v-6ddd02c6="" class="btn like-group"><div data-v-6ddd02c6="" class="btn-like"><a data-v-6ddd02c6="">喜欢</a></div> <div data-v-6ddd02c6="" class="modal-wrap"><a data-v-6ddd02c6="">16</a></div></div> <!----></div>
  <div class="share-group">
    <a class="share-circle" data-action="weixin-share" data-toggle="tooltip" data-original-title="分享到微信">
      <i class="iconfont ic-wechat"></i>
    </a>
    <a class="share-circle" data-action="weibo-share" data-toggle="tooltip" href="javascript:void((function(s,d,e,r,l,p,t,z,c){var%20f='http://v.t.sina.com.cn/share/share.php?appkey=1881139527',u=z||d.location,p=['&amp;url=',e(u),'&amp;title=',e(t||d.title),'&amp;source=',e(r),'&amp;sourceUrl=',e(l),'&amp;content=',c||'gb2312','&amp;pic=',e(p||'')].join('');function%20a(){if(!window.open([f,p].join(''),'mb',['toolbar=0,status=0,resizable=1,width=440,height=430,left=',(s.width-440)/2,',top=',(s.height-430)/2].join('')))u.href=[f,p].join('');};if(/Firefox/.test(navigator.userAgent))setTimeout(a,0);else%20a();})(screen,document,encodeURIComponent,'','','', '推荐 真依然很拉风 的文章《PySpark SQL常用语法》( 分享自 @简书 )','https://www.jianshu.com/p/177cbcb1cb6f?utm_campaign=maleskine&amp;utm_content=note&amp;utm_medium=reader_share&amp;utm_source=weibo','页面编码gb2312|utf-8默认gb2312'));" data-original-title="分享到微博">
      <i class="iconfont ic-weibo"></i>
    </a>
    <a class="share-circle" data-toggle="tooltip" id="longshare" target="_blank" data-original-title="" title="">
        <div class="qrcode" id="qrcode">
         <img src="//cdn2.jianshu.io/assets/web/download-index-side-qrcode-cb13fc9106a478795f8d10f9f632fccf.png" alt="Download index side qrcode">
         <p>下载app生成长微博图片</p>
         </div>
      <i class="iconfont ic-picture"></i>
    </a>
    <a class="share-circle more-share" tabindex="0" data-toggle="popover" data-placement="top" data-html="true" data-trigger="focus" href="javascript:void(0);" data-content="
      <ul class=&quot;share-list&quot;>
        <li><a href=&quot;javascript:void(function(){var d=document,e=encodeURIComponent,r='http://sns.qzone.qq.com/cgi-bin/qzshare/cgi_qzshare_onekey?url='+e('https://www.jianshu.com/p/177cbcb1cb6f?utm_campaign=maleskine&amp;utm_content=note&amp;utm_medium=reader_share&amp;utm_source=qzone')+'&amp;title='+e('推荐 真依然很拉风 的文章《PySpark SQL常用语法》'),x=function(){if(!window.open(r,'qzone','toolbar=0,resizable=1,scrollbars=yes,status=1,width=600,height=600'))location.href=r};if(/Firefox/.test(navigator.userAgent)){setTimeout(x,0)}else{x()}})();&quot;><i class=&quot;social-icon-sprite social-icon-zone&quot;></i><span>分享到QQ空间</span></a></li>
        <li><a href=&quot;javascript:void(function(){var d=document,e=encodeURIComponent,r='https://twitter.com/share?url='+e('https://www.jianshu.com/p/177cbcb1cb6f?utm_campaign=maleskine&amp;utm_content=note&amp;utm_medium=reader_share&amp;utm_source=twitter')+'&amp;text='+e('推荐 真依然很拉风 的文章《PySpark SQL常用语法》( 分享自 @jianshucom )')+'&amp;related='+e('jianshucom'),x=function(){if(!window.open(r,'twitter','toolbar=0,resizable=1,scrollbars=yes,status=1,width=600,height=600'))location.href=r};if(/Firefox/.test(navigator.userAgent)){setTimeout(x,0)}else{x()}})();&quot;><i class=&quot;social-icon-sprite social-icon-twitter&quot;></i><span>分享到Twitter</span></a></li>
        <li><a href=&quot;javascript:void(function(){var d=document,e=encodeURIComponent,r='https://www.facebook.com/dialog/share?app_id=483126645039390&amp;display=popup&amp;href=https://www.jianshu.com/p/177cbcb1cb6f?utm_campaign=maleskine&amp;utm_content=note&amp;utm_medium=reader_share&amp;utm_source=facebook',x=function(){if(!window.open(r,'facebook','toolbar=0,resizable=1,scrollbars=yes,status=1,width=450,height=330'))location.href=r};if(/Firefox/.test(navigator.userAgent)){setTimeout(x,0)}else{x()}})();&quot;><i class=&quot;social-icon-sprite social-icon-facebook&quot;></i><span>分享到Facebook</span></a></li>
        <li><a href=&quot;javascript:void(function(){var d=document,e=encodeURIComponent,r='https://plus.google.com/share?url='+e('https://www.jianshu.com/p/177cbcb1cb6f?utm_campaign=maleskine&amp;utm_content=note&amp;utm_medium=reader_share&amp;utm_source=google_plus'),x=function(){if(!window.open(r,'google_plus','toolbar=0,resizable=1,scrollbars=yes,status=1,width=450,height=330'))location.href=r};if(/Firefox/.test(navigator.userAgent)){setTimeout(x,0)}else{x()}})();&quot;><i class=&quot;social-icon-sprite social-icon-google&quot;></i><span>分享到Google+</span></a></li>
        <li><a href=&quot;javascript:void(function(){var d=document,e=encodeURIComponent,s1=window.getSelection,s2=d.getSelection,s3=d.selection,s=s1?s1():s2?s2():s3?s3.createRange().text:'',r='http://www.douban.com/recommend/?url='+e('https://www.jianshu.com/p/177cbcb1cb6f?utm_campaign=maleskine&amp;utm_content=note&amp;utm_medium=reader_share&amp;utm_source=douban')+'&amp;title='+e('PySpark SQL常用语法')+'&amp;sel='+e(s)+'&amp;v=1',x=function(){if(!window.open(r,'douban','toolbar=0,resizable=1,scrollbars=yes,status=1,width=450,height=330'))location.href=r+'&amp;r=1'};if(/Firefox/.test(navigator.userAgent)){setTimeout(x,0)}else{x()}})()&quot;><i class=&quot;social-icon-sprite social-icon-douban&quot;></i><span>分享到豆瓣</span></a></li>
      </ul>
    " data-original-title="" title="">更多分享</a>
  </div>
</div>

  <a id="web-note-ad-1" target="_blank" href="/apps/redirect?utm_source=note-bottom-click"><img src="//cdn2.jianshu.io/assets/web/web-note-ad-1-c2e1746859dbf03abe49248893c9bea4.png" alt="Web note ad 1"></a>

<!--
<div id="note-comment-above-ad-container">
  <span id="youdao-comment-ad" class="ad-badge">广告</span>
</div>
-->
<div><div id="comment-list" class="comment-list"><div><form class="new-comment"><a class="avatar"><img src="//cdn2.jianshu.io/assets/default_avatar/avatar_default-78d4d1f68984cd6d4379508dd94b4210.png"></a> <div class="sign-container"><a href="/sign_in?utm_source=desktop&amp;utm_medium=not-signed-in-comment-form" class="btn btn-sign">登录</a> <span>后发表评论</span></div></form> <!----></div> <!----> <div class="comments-placeholder" style="display: none;"><div class="author"><div class="avatar"></div> <div class="info"><div class="name"></div> <div class="meta"></div></div></div> <div class="text"></div> <div class="text animation-delay"></div> <div class="tool-group"><i class="iconfont ic-zan-active"></i><div class="zan"></div> <i class="iconfont ic-list-comments"></i><div class="zan"></div></div></div> <div id="normal-comment-list" class="normal-comment-list"><div><div><div class="top-title"><span>1条评论</span> <a class="author-only">只看作者</a> <a class="close-btn" style="display: none;">关闭评论</a> <div class="pull-right"><a class="active">按时间倒序</a><a class="">按时间正序</a></div></div></div> <!----> <!----> <div class="comments-placeholder" style="display: none;"><div class="author"><div class="avatar"></div> <div class="info"><div class="name"></div> <div class="meta"></div></div></div> <div class="text"></div> <div class="text animation-delay"></div> <div class="tool-group"><i class="iconfont ic-zan-active"></i><div class="zan"></div> <i class="iconfont ic-list-comments"></i><div class="zan"></div></div></div> <div id="comment-23943156" class="comment"><div><div class="author"><div data-v-f3bf5228="" class="v-tooltip-container" style="z-index: 0;"><div class="v-tooltip-content"><a href="/u/fc7499020f49" target="_blank" class="avatar"><img src="//upload.jianshu.io/users/upload_avatars/1932359/f25b33a61fce?imageMogr2/auto-orient/strip|imageView2/1/w/114/h/114/format/webp"></a>  </div> <!----></div> <div class="info"><a href="/u/fc7499020f49" target="_blank" class="name">真依然很拉风</a> <span class="author-tag">作者</span> <!----> <div class="meta"><span>2楼 · 2018.05.14 21:26</span></div></div></div> <div class="comment-wrap"><p>先占坑,以后慢慢完善</p> <!----> <div class="tool-group"><a data-v-cdecbe24="" id="like-button-23943156" class="like-button"><span data-v-cdecbe24="">赞</span></a> <a class=""><i class="iconfont ic-comment"></i> <span>回复</span></a> <!----> <!----></div></div></div> <div class="sub-comment-list hide"><!----> <!----></div></div></div></div> <!----> <div><!----></div></div></div>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值