版權宣告:本套技術專欄是作者(秦凱新)平時工作的總結和昇華,通過從真實商業環境抽取案例進行總結和分享,並給出商業應用的調優建議和叢集環境容量規劃等內容,請持續關注本套部落格。QQ郵箱地址:1120746959@qq.com,如有任何學術交流,可隨時聯絡。
1 Spark SQL 分組聚合統計
-
groupBy與agg搭配使用,agg(*exprs),這個方法是GroupedData上用於計算聚合資料的方法,*exprs可以是一個 string到string組成的字典,key是需要聚合的列名,value是用於計算的聚合函式的名稱。聚 合函式可以的取值有:avg, max, min, sum, count,mean。agg方法返回一個聚合後的 DataFrame物件。
df = spark.read.csv('/sql/customers.csv',header=True) df.columns df.groupBy('Genre').agg({"Age":"mean","Annual Income (k$)":"max","Spending Score (1-100)":"count"}).show() +------+-----------------------------+-----------------------+------------------+ | Genre|count(Spending Score (1-100))|max(Annual Income (k$))| avg(Age)| +------+-----------------------------+-----------------------+------------------+ |Female| 112| 99|38.098214285714285| | Male| 88| 99| 39.80681818181818| +------+-----------------------------+-----------------------+------------------+ 複製程式碼
-
除了使用字串以字典的方式指定,其實還可以使用聚合後的列的表示式來做相同的是,這 需要藉助pyspark.sql.functions模組中的方法。
from pyspark.sql.functions import * df = spark.read.csv('/sql/customers.csv',header=True) df.columns df.groupBy('Genre').agg(mean(df.Age)).show() +------+------------------+ | Genre| avg(Age)| +------+------------------+ |Female|38.098214285714285| | Male| 39.80681818181818| +------+------------------+ 複製程式碼
-
apply(udf),使用pandas中的使用者自定義函式作用在GroupedData的每一組資料之上,返 回結果作為一個DataFrame。udf使用者自定義函式接收pandas.DataFrame作為引數,返回另 外一個pandas.DataFrame物件。這個方法是pyspark2.3中加入的新方法。通過@pandas_udf表示這是一個pandas的方法,引數為id long,v double,指定PandasUDFType 為分組map操作。(測試未通過)
from pyspark.sql.functions import pandas_udf, PandasUDFType from pyspark.sql import SparkSession spark = SparkSession.builder.master('spark://hadoopmaste:7077').appName('apply').getOrCreate() df = spark.createDataFrame( [(1, 10.0), (1, 21.0), (2, 34.0), (2, 56.0), (2, 19.0)], ("id", "v")) @pandas_udf("id long, v double", PandasUDFType.GROUPED_MAP) def normalize(pdf): v = pdf.v print(type(v),type(pdf)) return pdf.assign(v=(v - v.mean()) / v.std()) df.groupby("id").apply(normalize).show() spark.stop() Pandas中DataFrame的assign方法是新建一個DataFrame而不會改變原來的DataFrame。 複製程式碼
-
avg(*cols),給算給定的數值型別的列的平均值
df = spark.read.csv('/sql/customers.csv',header=True) df.select(df.Age.cast('int').alias('age'),'Genre').groupBy('Genre').avg('age').show() +------+------------------+ | Genre| avg(age)| +------+------------------+ |Female|38.098214285714285| | Male| 39.80681818181818| +------+------------------+ 複製程式碼
-
count(),返回每個分組中資料的條數
df = spark.read.csv('/sql/customers.csv',header=True) df.select(df.Age.cast('int').alias('age'),'Genre').groupBy('Genre').count().show() 複製程式碼
-
max(*cols),計算給定列中數值最大的值。
df = spark.read.csv('/sql/customers.csv',header=True) df.select(df.Age.cast('int').alias('age'),'Genre','Annual Income (k$)').groupBy('Genre').max().show() 複製程式碼
-
mean(*cols)計算對應列的均值,列需要是數值型別
spark.read.csv('/sql/customers.csv',header=True) df.select(df.Age.cast('int').alias('age'),'Genre','Annual Income (k$)').groupBy('Genre').mean().show() 複製程式碼
-
min(*cols) 計算對應列的最小值,列數值型別需要是數值型別
spark.read.csv('/sql/customers.csv',header=True) df.select(df.Age.cast('int').alias('age'),'Genre','Annual Income (k$)').groupBy('Genre').min().show() 複製程式碼
-
sum(*cols),計算指定列的和,列的型別需要是數值型別。
spark.read.csv('/sql/customers.csv',header=True) df.select(df.Age.cast('int').alias('age'),'Genre','Annual Income (k$)').groupBy('Genre').sum().show() 複製程式碼
未完待續
2 總結
Python技術棧與Spark交叉資料分析雙向整合,讓我們在大資料融合分析達到了通用,可以發現Spark SQL 其實很大部分功能和Pandas雷同
秦凱新 於深圳 201812172352