pyspark学习-spark.sql.functions 聚合函数

https://spark.apache.org/docs/3.4.1/api/python/reference/pyspark.sql/functions.html
1. approx_count_distinct和count_distinct
#approx_count_distinct(col:ColumnOrName,rsd:Optionnal[float]=None)
"""
作用:返回列col的近似不同计数,返回一个新的列
场景:处理大数据计算时,获得一个精确结果开销很大,但是计算一个近似结果相对容易,此时可以使用approx_count_distinct函数
参数:
    col:列名
    rsd:结果允许的误差值,默认0.05
返回:
    column:返回计算结果列

"""
#count_distinct(col:columnOrName)
"""
作用:返回列col不同计数,返回一个新的列
场景:获得一个列准确的不同元素的个数
参数:
    col:列名
返回:
    column:返回计算结果列
"""
TEST_DATA_DIR = "/opt/software/tmp/"
def write(filename,data):
    with open(TEST_DATA_DIR+filename,'wt',encoding='utf-8') as f:
        f.write(data)

def generate_test_file():
    filename = "test.txt"
    #初始data
    data = ""
    data_format = "{} {} {}\n"#分别存放id,name,score 随机生成100000条数据,统计score列不同数量
    for i in range(100000):
        data += data_format.format(i+1,'jack'+str(i),random.randint(0,100))
    write(filename,data=data)
if __name__ == '__main__':
    generate_test_file()
    spark = SparkSession.builder.getOrCreate()
    schema = StructType([StructField("id",StringType(),True),
                         StructField("name",StringType(),True),
                         StructField("score",StringType(),True)])
    #读取文件
    data = spark.sparkContext.textFile(TEST_DATA_DIR+'test.txt').map(lambda x:x.split(' ')).map(lambda x:Row(x[0],x[1],x[2]))
    gradeDF=spark.createDataFrame(data,schema=schema)
    gradeDF.select(approx_count_distinct('score',rsd=0.01)).show()
    gradeDF.select(count_distinct('score')).show()

#输出结果
"""很明显是数据存在误差
+----------------------------+
|approx_count_distinct(score)|
+----------------------------+
|                          99|
+----------------------------+

+---------------------+
|count(DISTINCT score)|
+---------------------+
|                  101|
"""
+---------------------+
2. collect_list和collect_set:列转行
#collect_list(col:ColumnOrName)
"""
作用:返回col列的list副本,该函数返回值顺序不确定
场景:列转行
参数:
    col:列名
返回:
    column:返回col列的list副本
"""
#collect_set(col:ColumnOrName)
"""
作用:返回col列的set副本,该函数返回值顺序不确定
场景:列转行
参数:
    col:列名
返回:
    column:返回col列的set副本
"""
spark = SparkSession.builder.getOrCreate()
    #20110101销售商品数据
data = spark.createDataFrame([['20110101','A',22],['20110101','B',22],['20110102','A',33]],schema=['rq','produce_type','sl'])  #
 data.show()

 data.createOrReplaceTempView("data")
 spark.sql("select rq,collect_list(sl) as collect_list from data group by rq").show()
 spark.sql("select rq,collect_set(sl) as collect_set from data group by rq").show()
#输出结果
"""
+--------+------------+---+
|      rq|produce_type| sl|
+--------+------------+---+
|20110101|           A| 22|
|20110101|           B| 22|
|20110102|           A| 33|
+--------+------------+---+

+--------+------------+
|      rq|collect_list|
+--------+------------+
|20110101|    [22, 22]|
|20110102|        [33]|
+--------+------------+

+--------+-----------+
|      rq|collect_set|
+--------+-----------+
|20110101|       [22]|
|20110102|       [33]|
+--------+-----------+
"""
3. corr:皮尔逊相关性
#corr(col1:ColumnOrName,col2:ColumnOrName)
"""
作用:返回col1列和col2列的皮尔逊相关系数
场景:
参数:
    col1:列名
    col2:列名
返回:
    column:返回col1列和col2列的皮尔逊相关系数
"""
spark = SparkSession.builder.getOrCreate()
a = range(20)
b = [2 * x for x in a]
data = spark.createDataFrame(zip(a,b),schema=['a','b'])
data.agg(corr('a','b').alias('c')).show()
data.createOrReplaceTempView("data")
spark.sql("select corr(a,b) as c from data").show()
#输出结果
"""
+---+
|  c|
+---+
|1.0|
+---+

+---+
|  c|
+---+
|1.0|
+---+
"""
4. covar_pop和covar_sample:返回列的总体协方差和样本协方差
#covar_pop(col1:ColumnOrName,col2:ColumnOrName)
"""
作用:返回col1列和col2列的总体协方差
场景:
参数:
    col1:列名
    col2:列名
返回:
    column:返回col1列和col2列的协方差
公式:
    u0:x平均值  u1:y平均值
    cov(x,y) = ((x1-u0)*(y1-u1)+(x2-u0)*(y2-u1)+...+(xN-u0)*(yN-u1))/N
例子:
    X = [1,2,3]  Y = [3,6,9]   
    u = 2            u = 6
    cov(x,y) = ((1-2)*(3-6)+(2-2)*(6-6)+(3-2)*(6-9))/3 = 2
"""
#cover_samp(col1:ColumnOrName,col2:ColumnOrName)
"""
作用:返回col1列和col2列的样本协方差
场景:
参数:
    col1:列名
    col2:列名
返回:
    column:返回col1列和col2列的样本协方差
公式:
    u0:x平均值  u1:y平均值
    cov(x,y) = ((x1-u0)*(y1-u1)+(x2-u0)*(y2-u1)+...+(xN-u0)*(yN-u1))/(N-1)
例子:
    X = [1,2,3]  Y = [3,6,9]   
    u = 2            u = 6
    cov(x,y) = ((1-2)*(3-6)+(2-2)*(6-6)+(3-2)*(6-9))/2 = 3

"""

#总体协方差和样本协方差区别重点是分母不同,总体协方差为N,样本协方差为N-1

spark = SparkSession.builder.getOrCreate()
data = spark.createDataFrame([(1,3),(2,6),(3,9)],schema=['a','b'])  
# ((1-2)*(3-6)+(2-2)*(6-6)+(3-2)*(9-6))/3 = 2
data.agg(covar_pop('a','b').alias('covar_pop')).show()
data.agg(covar_samp('a','b').alias('covar_samp')).show() 
#((1-2)*(3-6)+(2-2)*(6-6)+(3-2)*(9-6))/2 = (3+3)/2 = 3
#输出如下:
+---------+
|covar_pop|
+---------+
|      2.0|
+---------+

+----------+
|covar_samp|
+----------+
|       3.0|
+----------+
5. first:返回集合中第一个元素  last:返回集合中最后一个元素
#first(col:ColumnOrName,ignorenulls:ColumnOrName)
"""
作用:返回该组第一个数值,和groupBy合用,会显示分组之后,各个组的第一个
场景:
参数:
    col:列名
    ignorenulls:是否忽略控制
返回:
    column:返回该组第一个数值
"""
#last(col:ColumnOrName,ignorenulls:ColumnOrName)
"""
作用:返回该组第最后一个数值,和groupBy合用,会显示分组之后,各个组的最后一个
场景:
参数:
    col:列名
    ignorenulls:是否忽略控制
返回:
    column:返回该组第最后一个数值
"""
data = spark.createDataFrame([('Alice',2),('Bob',5),('Alice',12),('Bob',32),('Alice',None)],schema=("name","age"))
print("按照age排序前")
data.groupby('name').agg(first("age")).show()
data.groupby('name').agg(first("age", ignorenulls=True)).show()

print("按照age倒排序后")
data = data.orderBy("age",ascending=False)
data.groupby('name').agg(first("age")).show()
data.groupby('name').agg(first("age", ignorenulls=True)).show()

#last
   
data.groupby('name').agg(last("age")).show()
data.groupby('name').agg(last("age", ignorenulls=True)).show()

print("按照age倒排序后")
data = data.orderBy("age", ascending=False)
data.groupby('name').agg(last("age")).show()
data.groupby('name').agg(last("age", ignorenulls=True)).show()

#输出如下:
"""
按照age排序前
+-----+----------+
| name|first(age)|
+-----+----------+
|  Bob|         5|
|Alice|         2|
+-----+----------+

+-----+----------+
| name|first(age)|
+-----+----------+
|  Bob|         5|
|Alice|         2|
+-----+----------+

按照age倒排序后
+-----+----------+
| name|first(age)|
+-----+----------+
|  Bob|        32|
|Alice|        12|
"""

data = data.sort(data['age'].asc())

data.createOrReplaceTempView("data")
spark.sql("select name,first(age) from data  where age >0 group by name ").show()
#输出如下:
"""
+-----+----------+
| name|first(age)|
+-----+----------+
|  Bob|         5|
|Alice|         2|
+-----+----------+

#last
+-----+---------+
| name|last(age)|
+-----+---------+
|  Bob|       32|
|Alice|     null|
+-----+---------+

+-----+---------+
| name|last(age)|
+-----+---------+
|  Bob|       32|
|Alice|       12|
+-----+---------+

按照age倒排序后
+-----+---------+
| name|last(age)|
+-----+---------+
|  Bob|        5|
|Alice|     null|
+-----+---------+

+-----+---------+
| name|last(age)|
+-----+---------+
|  Bob|        5|
|Alice|        2|
+-----+---------+
"""
6. grouping:判断是否聚合
#grouping(col:ColumnOrName)
"""
作用:
场景:
参数:
    col:列名
返回:
    column:如果聚合返回1,否则返回0
"""
data = spark.createDataFrame([('Alice', 2), ('Bob', 5), ('Alice', 12), ('Bob', 32)],
                                 schema=("name", "age"))
data.cube('name').agg(grouping('name'),count("age")).show()
#输出如下:
"""
data = spark.createDataFrame([('Alice', 2), ('Bob', 5), ('Alice', 12), ('Bob', 32)],
                                 schema=("name", "age"))
data.cube('name').agg(grouping('name'),count("age")).show()
"""
7.max\min\mean\median\sum\avg\count\product
"""
max:返回集合中最大元素  
min:返回集合中最小元素  
mean:返回集合元素中平均数  过滤空值
avg:和mean一样            过滤空值
median:返回结合中元素中位数    
sum:返回集合元素中元素之和 
count:返回集合元素个数     过滤空值
product:返回集合中元素的乘积
"""
"""
作用:
场景:
参数:
    col:列名
返回:
    column:返回对应结果
"""
#姓名  科目  成绩
data = spark.createDataFrame([('tom','math',32),('tom','english',50),('tom','chinese',90),
('jack','math',62),('jack','english',70),('jack','chinese',80),
('danny','math',92),('danny','english',80),('danny','chinese',70)
],schema=['name','subject','score'])

#最大元素
data.groupby('name').agg(max('score')).show()
data.agg(max('score')).show()
#输出如下:
+-----+----------+
| name|max(score)|
+-----+----------+
| jack|        80|
|  tom|        90|
|danny|        92|
+-----+----------+

+----------+
|max(score)|
+----------+
|        92|
+----------+
#最小元素
data.groupby('subject').agg(min('score')).show()
data.agg(min('score')).show()
#输出如下:
+-----+----------+
| name|min(score)|
+-----+----------+
| jack|        62|
|  tom|        32|
|danny|        70|
+-----+----------+

+----------+
|min(score)|
+----------+
|        32|
+----------+
#mean平均值
#最大元素
data.groupby('name').agg(mean('score')).show()
data.agg(mean('score')).show()
#输出如下:
+-----+------------------+
| name|        avg(score)|
+-----+------------------+
| jack| 70.66666666666667|
|  tom|57.333333333333336|
|danny| 80.66666666666667|
+-----+------------------+

+-----------------+
|       avg(score)|
+-----------------+
|69.55555555555556|
+-----------------+
#median中位数
data.groupby('name').agg(median('score')).show()
data.agg(median('score')).show()
#sum求和
data.groupby('name').agg(sum('score')).show()
data.agg(sum('score')).show()
#输出如下:
"""
+-----+----------+
| name|sum(score)|
+-----+----------+
| jack|       212|
|  tom|       172|
|danny|       242|
+-----+----------+

+----------+
|sum(score)|
+----------+
|       626|
+----------+
"""
#count元素个数
data.groupby('name').agg(count('score')).show()
data.agg(count('score')).show()
#输出如下:
"""
+-----+------------+
| name|count(score)|
+-----+------------+
| jack|           3|
|  tom|           3|
|danny|           3|
+-----+------------+

+------------+
|count(score)|
+------------+
|           9|
+------------+
"""
#product:返回乘积
data.groupby('name').agg(product('score')).show()
data.agg(product('score')).show()
#输出如下:
+-----+--------------+
| name|product(score)|
+-----+--------------+
| jack|      347200.0|
|  tom|      144000.0|
|danny|      515200.0|
+-----+--------------+

+--------------+
|product(score)|
+--------------+
|2.575835136E16|
+--------------+
 8. sum_distinct:不同元素求和
#sum_distinct不同元素求和,只有列中元素不同才进行加法运算
"""
作用:
场景:
参数:
    col:列名
返回:
    column:返回对应结果
"""
spark = SparkSession.builder.getOrCreate()
data = spark.createDataFrame([('tom', 'math', 32), ('tom', 'english', 32), ('tom', 'chinese', 32), ('jack', 'math', 32), ('jack', 'english', 32), ('jack', 'chinese', 32),
('danny', 'math', 32), ('danny', 'english', 32), ('danny', 'chinese', 32)], schema=['name', 'subject', 'score'])

data.groupby('name').agg(sum_distinct('score')).show()
data.agg(sum_distinct('score')).show()
#输出如下:
"""
+-----+-------------------+
| name|sum(DISTINCT score)|
+-----+-------------------+
| jack|                 32|
|danny|                 32|
|  tom|                 32|
+-----+-------------------+

+-------------------+
|sum(DISTINCT score)|
+-------------------+
|                 32|
+-------------------+
"""
9. var_pop:方差  var_pop:样本方差  variance:方差
#如果数据集合存在空值,则过滤掉,分母也减掉这个元素
#var_pop:返回该列的总体方差
"""
作用:
场景:
参数:
    col:列名
返回:
    column:返回对应结果
公式:
    u:(x1,x2,...,XN)平均数
    [(x1-u)**2+(x2-u)**2+...+(xN-u)**2]/N
"""

#var_samp:返回该列的样本方差
"""
作用:
场景:
参数:
    col:列名
返回:
    column:返回对应结果
公式:
    u:(x1,x2,...,XN)平均数
    [(x1-u)**2+(x2-u)**2+...+(xN-u)**2]/(N-1)
"""
#variance:方差,公式和var_samp一致
spark = SparkSession.builder.getOrCreate()
data = spark.createDataFrame([('tom', 'math', 1), ('tom', 'english', 2), ('tom', 'chinese', 3),('jack', 'math', 1), ('jack', 'english', 2), ('jack', 'chinese', 3),
('danny', 'math', 1), ('danny', 'english', 2), ('danny', 'chinese', 3)], schema=['name', 'subject', 'score'])

data.groupBy('name').agg(var_pop("score")).show()
data.agg(var_pop("score")).show()

#var_pop   x = 1 2 3  u=2   [(1-2)**2+(2-2)**2+(3-2)**2]/3 = 0.66666
#输出如下:
"""
+-----+------------------+
| name|    var_pop(score)|
+-----+------------------+
| jack|0.6666666666666666|
|  tom|0.6666666666666666|
|danny|0.6666666666666666|
+-----+------------------+

+------------------+
|    var_pop(score)|
+------------------+
|0.6666666666666666|
+------------------+
"""
#var_samp:样本方差
data.groupBy('name').agg(var_samp("score")).show()
data.agg(var_samp("score")).show()
#输出如下:
"""
+-----+---------------+
| name|var_samp(score)|
+-----+---------------+
| jack|            1.0|
|  tom|            1.0|
|danny|            1.0|
+-----+---------------+

+---------------+
|var_samp(score)|
+---------------+
|           0.75|
+---------------+
"""
#测试存在None值
   spark = SparkSession.builder.getOrCreate()
    data = spark.createDataFrame([('tom', 'math', 1), ('tom', 'english', 2), ('tom', 'chinese', None) ], schema=['name', 'subject', 'score'])

 
data.groupBy('name').agg(var_pop("score")).show()  
#均值:(1+2)/2=1.5  方差((1-1.5)**2+(2-1.5)**2)/2 = 0.25
#输出如下:
"""
+-----+------------------+
| name|    var_pop(score)|
+-----+------------------+
|tom|              0.25|
+-----+------------------+
"""
10. stddev:标准差  stddev_pop:总体标准差  stddev_samp:样本标准差
#如果数据集合存在空值,则过滤掉,分母也减掉这个元素
#stddev:返回该列的标准差
"""
作用:
场景:
参数:
    col:列名
返回:
    column:返回对应结果
公式:
    u:(x1,x2,...,XN)平均数
    math.sqrt([(x1-u)**2+(x2-u)**2+...+(xN-u)**2]/(N-1))
"""
#stddev_pop:返回该列的总体标准差
"""
作用:
场景:
参数:
    col:列名
返回:
    column:返回对应结果
公式:
    u:(x1,x2,...,XN)平均数
    math.sqrt([(x1-u)**2+(x2-u)**2+...+(xN-u)**2]/N)
"""
#stddev_samp:返回该列的样本标准差
"""
作用:
场景:
参数:
    col:列名
返回:
    column:返回对应结果
公式:
    u:(x1,x2,...,XN)平均数
    math.sqrt([(x1-u)**2+(x2-u)**2+...+(xN-u)**2]/(N-1))
"""
spark = SparkSession.builder.getOrCreate()
data = spark.createDataFrame([('tom', 'math', 3), ('tom', 'english', 4), ('tom', 'chinese', 5),('jack', 'math', 3), ('jack', 'english', 4), ('jack', 'chinese', 5),
('danny', 'math', 3), ('danny', 'english', 4), ('danny', 'chinese', 5)], schema=['name', 'subject', 'score'])

    # 最大元素
    data.groupBy('name').agg(stddev("score").alias('stddev')).show()  #mean:过滤空值  avg:过滤空值
    data.groupBy('name').agg(stddev_pop("score")).show()
    data.groupBy('name').agg(stddev_samp("score")).show()
#输出如下:
"""
+-----+------+
| name|stddev|
+-----+------+
| jack|   1.0|
|  tom|   1.0|
|danny|   1.0|
+-----+------+

+-----+-----------------+
| name|stddev_pop(score)|
+-----+-----------------+
| jack|0.816496580927726|
|  tom|0.816496580927726|
|danny|0.816496580927726|
+-----+-----------------+

+-----+------------------+
| name|stddev_samp(score)|
+-----+------------------+
| jack|               1.0|
|  tom|               1.0|
|danny|               1.0|
+-----+------------------+
"""

你可能感兴趣的:(spark,spark)