通过例子学习spark dataframe -- transformations函数(2)
来源:互联网 发布:分布式数据库的安全性 编辑:程序博客网 时间:2024/06/07 22:19
- 通过例子学习spark dataframe transformations函数2
- 说明
- 数据说明
- agg
- groupBy
- apply 和 col
- cube
- drop
- join
- na
- select
- withColumn 和 withColumnRenamed
- stat
- 说明
通过例子学习spark dataframe – transformations函数(2)
说明
transformations函数分为两类:
* Typed transformations
这类函数的返回值一般都是dataset,也就是说不会改变原来的数据集的类型。
* Untyped transformations
这类函数的返回值,会根据不同的函数返回不同的类型。
本文的所有例子,都是基于spark-2.1进行操作。
本文的所有例子,都是基于以下简单的csv数据集进行讲解:
数据说明
import org.apache.spark.sql.SparkSessionval spark = SparkSession.builder().appName("Spark SQL basic example").config("spark.some.config.option", "some-value").getOrCreate()import spark.implicits._val df = spark.read.format("csv").option("header", true).load("/user/hadoop/csvdata/csvdata")df.show()scala >scala> df.show()+---+----+-------+-----+| id|name|subject|score|+---+----+-------+-----+| 1| n1| s1| 10|| 2| n2| s2| 20|| 3| n3| s3| 30|| 3| n3| s1| 20|| 4| n4| s2| 40|| 5| n5| s3| 50|| 6| n6| s1| 60|| 7| n6| s2| 40|| 8| n8| s3| 90|| 8| n9| s1| 30|| 9| n9| s1| 20|| 9| n9| s2| 70|+---+----+-------+-----+
agg
- 功能说明
在整个数据集范围类进行聚合操作。该函数相当于:
ds.groupBy().agg(...)
- 函数原型
def agg(expr: Column, exprs: Column*): DataFrame def agg(exprs: Map[String, String]): DataFrame def agg(exprs: Map[String, String]): DataFrame def agg(aggExpr: (String, String), aggExprs: (String, String)*): DataFrame
- 例子1
scala> df.agg("score"->"avg", "score"->"max", "score"->"min", "score"->"count").show()+----------+----------+----------+------------+|avg(score)|max(score)|min(score)|count(score)|+----------+----------+----------+------------+| 40.0| 90| 10| 12|+----------+----------+----------+------------+
groupBy
功能
使用指定的列对数据集进行分组,以便我们可以对其进行聚合。请参阅RelationalGroupedDataset获取所有可用的聚合函数。
这是groupBy的一个变体,它只能使用列名称对现有列进行分组(即不能构造表达式)。函数原型
def groupBy(col1: String, cols: String*): RelationalGroupedDataset def groupBy(cols: Column*): RelationalGroupedDataset
- 例子1
在使用groupBy函数时,一般都是先分组,在使用agg等聚合函数对数据进行聚合。
按name字段进行聚合,然后再使用agg聚合函数进行聚合。
scala> df.groupBy("name").agg("score"->"avg").sort("name").show()+----+----------+|name|avg(score)|+----+----------+| n1| 10.0|| n2| 20.0|| n3| 25.0|| n4| 40.0|| n5| 50.0|| n6| 50.0|| n8| 90.0|| n9| 40.0|+----+----------+
- 例子2
按id和name两个字段对数据集进行分组,然后求score列的平均值。
scala> df.groupBy("id","name").agg("score"->"avg").sort("name").show()+---+----+----------+| id|name|avg(score)|+---+----+----------+| 1| n1| 10.0|| 2| n2| 20.0|| 3| n3| 25.0|| 4| n4| 40.0|| 5| n5| 50.0|| 7| n6| 40.0|| 6| n6| 60.0|| 8| n8| 90.0|| 9| n9| 45.0|| 8| n9| 30.0|+---+----+----------+
- 例子3
计算每个subject的平均分数:
scala> df.groupBy("subject").agg("score"->"avg").sort("subject").show()+-------+------------------+|subject| avg(score)|+-------+------------------+| s1| 28.0|| s2| 42.5|| s3|56.666666666666664|+-------+------------------+
- 例子4
同时计算多个列值的平均值,最小值,最大值。
(注:我这里用的是同一列,完全可以是不同列)
scala> df.groupBy("subject").agg("score"->"avg", "score"->"max", "score"->"min", "score"->"count").sort("subject").show()+-------+------------------+----------+----------+------------+|subject| avg(score)|max(score)|min(score)|count(score)|+-------+------------------+----------+----------+------------+| s1| 28.0| 60| 10| 5|| s2| 42.5| 70| 20| 4|| s3|56.666666666666664| 90| 30| 3|+-------+------------------+----------+----------+------------+
apply 和 col
功能说明
根据列名选择列并将其作为列返回。函数原型
def apply(colName: String): Column def col(colName: String): Column
- 例子1
scala> df.apply("name")res11: org.apache.spark.sql.Column = namescala> df.col("name")res16: org.apache.spark.sql.Column = name
cube
功能说明
使用指定的列为当前数据集创建一个多维数据集,因此我们可以对它们运行聚合。请参阅RelationalGroupedDataset获取所有可用的聚合函数。
这是立方体的变体,只能使用列名称对现有列进行分组(即不能构造表达式)。原型
def cube(col1: String, cols: String*): RelationalGroupedDataset def cube(cols: Column*): RelationalGroupedDataset
- 例子1
scala> df.cube("name", "score")res18: org.apache.spark.sql.RelationalGroupedDataset = org.apache.spark.sql.RelationalGroupedDataset@3f88db17
drop
函数功能
删除数据集中的某个列。函数原型
def drop(col: Column): DataFrame def drop(colNames: String*): DataFrame def drop(colName: String): DataFrame
- 例子1
scala> df.drop("id").show()+----+-------+-----+|name|subject|score|+----+-------+-----+| n1| s1| 10|| n2| s2| 20|| n3| s3| 30|| n3| s1| 20|| n4| s2| 40|| n5| s3| 50|| n6| s1| 60|| n6| s2| 40|| n8| s3| 90|| n9| s1| 30|| n9| s1| 20|| n9| s2| 70|+----+-------+-----+
join
join类型的说明
内连接 : 只连接匹配的行
左外连接 : 包含左边表的全部行(不管右边的表中是否存在与它们匹配的行),以及右边表中全部匹配的行
右外连接 : 包含右边表的全部行(不管左边的表中是否存在与它们匹配的行),以及左边表中全部匹配的行
全外连接 : 包含左、右两个表的全部行,不管另外一边的表中是否存在与它们匹配的行。功能说明
使用给定的连接表达式连接另一个DataFrame。以下执行df1和df2之间的完整外部联接。
使用给定的连接表达式与另一个DataFrame进行内部连接。
使用给定的列与另一个DataFrame进行设置连接。
加入另一个DataFrame。函数原型
def join(right: Dataset[_], joinExprs: Column, joinType: String): DataFrame def join(right: Dataset[_], joinExprs: Column): DataFrame def join(right: Dataset[_], usingColumns: Seq[String], joinType: String): DataFrame def join(right: Dataset[_], usingColumns: Seq[String]): DataFrame // 内部使用给定的列与另一个DataFrame进行同等连接。def join(right: Dataset[_], usingColumn: String): DataFrame def join(right: Dataset[_]): DataFrame
注意:这里的joinType必须是这几个中的一个:inner
, outer
, left_outer
, right_outer
, leftsemi
.
- 例子1
该例子演示inner join。
scala> df.show()+---+----+-------+-----+| id|name|subject|score|+---+----+-------+-----+| 1| n1| s1| 10|| 2| n2| s2| 20|| 3| n3| s3| 30|| 3| n3| s1| 20|| 4| n4| s2| 40|| 5| n5| s3| 50|| 6| n6| s1| 60|| 7| n6| s2| 40|| 8| n8| s3| 90|| 8| n9| s1| 30|| 9| n9| s1| 20|| 9| n9| s2| 70|+---+----+-------+-----+scala> val df2 = df.select("id", "subject","score")df2: org.apache.spark.sql.DataFrame = [id: string, subject: string ... 1 more field]scala> df2.show()+---+-------+-----+| id|subject|score|+---+-------+-----+| 1| s1| 10|| 2| s2| 20|| 3| s3| 30|| 3| s1| 20|| 4| s2| 40|| 5| s3| 50|| 6| s1| 60|| 7| s2| 40|| 8| s3| 90|| 8| s1| 30|| 9| s1| 20|| 9| s2| 70|+---+-------+-----+scala> val df3 = df.join(df2, df("id")===df2("id"))17/12/03 21:40:59 WARN Column: Constructing trivially true equals predicate, 'id#0 = id#0'. Perhaps you need to use aliases.df3: org.apache.spark.sql.DataFrame = [id: string, name: string ... 5 more fields]scala> df3.show()+---+----+-------+-----+---+-------+-----+| id|name|subject|score| id|subject|score|+---+----+-------+-----+---+-------+-----+| 1| n1| s1| 10| 1| s1| 10|| 2| n2| s2| 20| 2| s2| 20|| 3| n3| s3| 30| 3| s1| 20|| 3| n3| s3| 30| 3| s3| 30|| 3| n3| s1| 20| 3| s1| 20|| 3| n3| s1| 20| 3| s3| 30|| 4| n4| s2| 40| 4| s2| 40|| 5| n5| s3| 50| 5| s3| 50|| 6| n6| s1| 60| 6| s1| 60|| 7| n6| s2| 40| 7| s2| 40|| 8| n8| s3| 90| 8| s1| 30|| 8| n8| s3| 90| 8| s3| 90|| 8| n9| s1| 30| 8| s1| 30|| 8| n9| s1| 30| 8| s3| 90|| 9| n9| s1| 20| 9| s2| 70|| 9| n9| s1| 20| 9| s1| 20|| 9| n9| s2| 70| 9| s2| 70|| 9| n9| s2| 70| 9| s1| 20|+---+----+-------+-----+---+-------+-----+scala> val df4 = df2.limit(6)df4: org.apache.spark.sql.Dataset[org.apache.spark.sql.Row] = [id: string, subject: string ... 1 more field]scala> df4.show()+---+-------+-----+| id|subject|score|+---+-------+-----+| 1| s1| 10|| 2| s2| 20|| 3| s3| 30|| 3| s1| 20|| 4| s2| 40|| 5| s3| 50|+---+-------+-----+scala> df.show()+---+----+-------+-----+| id|name|subject|score|+---+----+-------+-----+| 1| n1| s1| 10|| 2| n2| s2| 20|| 3| n3| s3| 30|| 3| n3| s1| 20|| 4| n4| s2| 40|| 5| n5| s3| 50|| 6| n6| s1| 60|| 7| n6| s2| 40|| 8| n8| s3| 90|| 8| n9| s1| 30|| 9| n9| s1| 20|| 9| n9| s2| 70|+---+----+-------+-----+scala> val df6 = df.join(df4, "id")df6: org.apache.spark.sql.DataFrame = [id: string, name: string ... 4 more fields]scala> df6.show()+---+----+-------+-----+-------+-----+| id|name|subject|score|subject|score|+---+----+-------+-----+-------+-----+| 1| n1| s1| 10| s1| 10|| 2| n2| s2| 20| s2| 20|| 3| n3| s3| 30| s1| 20|| 3| n3| s3| 30| s3| 30|| 3| n3| s1| 20| s1| 20|| 3| n3| s1| 20| s3| 30|| 4| n4| s2| 40| s2| 40|| 5| n5| s3| 50| s3| 50|+---+----+-------+-----+-------+-----+
- 例子2
本例说明left_outer的使用和结果。
注意:数据集df4和df与上例的相同。
小结:通过例子可以看到,left_outer的效果是,保留左边表格的所有id,即使右边的表没有这些id(关联字段的值)
scala> df4.show()+---+-------+-----+| id|subject|score|+---+-------+-----+| 1| s1| 10|| 2| s2| 20|| 3| s3| 30|| 3| s1| 20|| 4| s2| 40|| 5| s3| 50|+---+-------+-----+scala> df.show()+---+----+-------+-----+| id|name|subject|score|+---+----+-------+-----+| 1| n1| s1| 10|| 2| n2| s2| 20|| 3| n3| s3| 30|| 3| n3| s1| 20|| 4| n4| s2| 40|| 5| n5| s3| 50|| 6| n6| s1| 60|| 7| n6| s2| 40|| 8| n8| s3| 90|| 8| n9| s1| 30|| 9| n9| s1| 20|| 9| n9| s2| 70|+---+----+-------+-----+scala> val df7 = df.join(df4, df("id")===df4("id"), "left_outer")17/12/03 21:53:40 WARN Column: Constructing trivially true equals predicate, 'id#0 = id#0'. Perhaps you need to use aliases.df7: org.apache.spark.sql.DataFrame = [id: string, name: string ... 5 more fields]scala> df7.show()+---+----+-------+-----+----+-------+-----+| id|name|subject|score| id|subject|score|+---+----+-------+-----+----+-------+-----+| 1| n1| s1| 10| 1| s1| 10|| 2| n2| s2| 20| 2| s2| 20|| 3| n3| s3| 30| 3| s1| 20|| 3| n3| s3| 30| 3| s3| 30|| 3| n3| s1| 20| 3| s1| 20|| 3| n3| s1| 20| 3| s3| 30|| 4| n4| s2| 40| 4| s2| 40|| 5| n5| s3| 50| 5| s3| 50|| 6| n6| s1| 60|null| null| null|| 7| n6| s2| 40|null| null| null|| 8| n8| s3| 90|null| null| null|| 8| n9| s1| 30|null| null| null|| 9| n9| s1| 20|null| null| null|| 9| n9| s2| 70|null| null| null|+---+----+-------+-----+----+-------+-----+
na
功能说明
返回一个DataFrameNaFunctions以处理丢失的数据。函数原型
def na: DataFrameNaFunctions
注意:该函数会返回一个类型的类,该类包含了各种操作空列的函数。
这些函数包括:drop(),fill(),replace(),fillCol(),replaceCol()
- 例子1
// 删除包含任何空值的行scala> df.na.drop()
- 例子2
// 使用常量值填充空值scala> df.na.fill("null")
select
功能说明
选择一组列。注意:该函数返回的是一个DataFrame类。函数原型
// 这是select的一个变体,只能使用列名选择现有的列(即不能构造表达式)。def select(col: String, cols: String*): DataFrame // 选择一组基于列的表达式。def select(cols: Column*): DataFrame // 选择一组SQL表达式。这是接受SQL表达式的select的一个变体。def selectExpr(exprs: String*): DataFrame
- 例子1
scala> df.select("id", "score").show()+---+-----+| id|score|+---+-----+| 1| 10|| 2| 20|| 3| 30|| 3| 20|| 4| 40|| 5| 50|| 6| 60|| 7| 40|| 8| 90|| 8| 30|| 9| 20|| 9| 70|+---+-----+
- 例子2:对select的列值进行操作
scala> df.select($"id", $"score"*10).show()+---+------------+| id|(score * 10)|+---+------------+| 1| 100.0|| 2| 200.0|| 3| 300.0|| 3| 200.0|| 4| 400.0|| 5| 500.0|| 6| 600.0|| 7| 400.0|| 8| 900.0|| 8| 300.0|| 9| 200.0|| 9| 700.0|+---+------------+
- 例子3:selectExpr的使用(select表达式)
ds.selectExpr("colA", "colB as newName", "abs(colC)")或ds.select(expr("colA"), expr("colB as newName"), expr("abs(colC)"))scala> df.selectExpr("id", "score * 10").show()+---+------------+| id|(score * 10)|+---+------------+| 1| 100.0|| 2| 200.0|| 3| 300.0|| 3| 200.0|| 4| 400.0|| 5| 500.0|| 6| 600.0|| 7| 400.0|| 8| 900.0|| 8| 300.0|| 9| 200.0|| 9| 700.0|+---+------------+或scala> df.selectExpr("id", "score as points").show()+---+------+| id|points|+---+------+| 1| 10|| 2| 20|| 3| 30|... ...
withColumn 和 withColumnRenamed
功能说明
通过添加一列或替换具有相同名称的现有列来返回新的数据集。
withColumnRenamed只是重命名列。
注意:该函数非常常用,可以和Column类的函数结合实现非常强大的数据集操作的功能。
我会在《spark dataframe实践》一文中进行讲解这类应用。函数原型
def withColumn(colName: String, col: Column): DataFrame def withColumnRenamed(existingName: String, newName: String): DataFrame
- 例子1:通过重命名现有列来添加新列
scala> val df8 = df.withColumn("subs", df("subject"))df8: org.apache.spark.sql.DataFrame = [id: string, name: string ... 3 more fields]scala> df8.show()+---+----+-------+-----+----+| id|name|subject|score|subs|+---+----+-------+-----+----+| 1| n1| s1| 10| s1|| 2| n2| s2| 20| s2|| 3| n3| s3| 30| s3|| 3| n3| s1| 20| s1|| 4| n4| s2| 40| s2|| 5| n5| s3| 50| s3|| 6| n6| s1| 60| s1|| 7| n6| s2| 40| s2|| 8| n8| s3| 90| s3|| 8| n9| s1| 30| s1|| 9| n9| s1| 20| s1|| 9| n9| s2| 70| s2|+---+----+-------+-----+----+
- 例子2:重命名现有列,但不添加新列
从下面的例子中可以看出,把score列的值替换了,但并没有添加新的列。
scala> val df9 = df.withColumn("score", df("score")/100)df9: org.apache.spark.sql.DataFrame = [id: string, name: string ... 2 more fields]scala> df9.show()+---+----+-------+-----+| id|name|subject|score|+---+----+-------+-----+| 1| n1| s1| 0.1|| 2| n2| s2| 0.2|| 3| n3| s3| 0.3|| 3| n3| s1| 0.2|| 4| n4| s2| 0.4|| 5| n5| s3| 0.5|| 6| n6| s1| 0.6|| 7| n6| s2| 0.4|| 8| n8| s3| 0.9|| 8| n9| s1| 0.3|| 9| n9| s1| 0.2|| 9| n9| s2| 0.7|+---+----+-------+-----+// 也可以直接通过withColumnRenamed进行重命名scala> val df9 = df.withColumnRenamed("score","score2") df9: org.apache.spark.sql.DataFrame = [id: string, name: string ... 2 more fields]scala> df9.show()+---+----+-------+------+| id|name|subject|score2|+---+----+-------+------+| 1| n1| s1| 10|| 2| n2| s2| 20|| 3| n3| s3| 30|| 3| n3| s1| 20|| 4| n4| s2| 40|| 5| n5| s3| 50|| 6| n6| s1| 60|| 7| n6| s2| 40|| 8| n8| s3| 90|| 8| n9| s1| 30|| 9| n9| s1| 20|| 9| n9| s2| 70|+---+----+-------+------+
stat
功能说明
为工作统计功能支持返回一个DataFrameStatFunctions。
该类的函数包括:approxQuantile,corr,cov,freqItems,sampleBy,countMinSketch,bloomFilter,buildBloomFilter等函数原型
def stat: DataFrameStatFunctions
- 例子1
scala> val cols = Array("score")cols: Array[String] = Array(score)scala> df.stat.freqItems(cols)res56: org.apache.spark.sql.DataFrame = [score_freqItems: array<string>]scala> df.stat.freqItems(cols).show()+--------------------+| score_freqItems|+--------------------+|[90, 30, 60, 50, ...|+--------------------+
- 通过例子学习spark dataframe -- transformations函数(2)
- 通过例子学习spark dataframe -- transformations函数(1)
- 通过例子学习spark rdd--Transformations函数
- 通过例子学习spark dataframe--基础函数和Action函数
- 通过例子学习spark rdd--Action函数
- spark dataframe函数编程
- spark dataset,dataframe学习
- spark DataFrame学习手册
- 学习spark:二、RDD的Transformations操作
- spark之DataFrame 通过反射创建
- Spark之DataFrame通过编码创建
- spark学习-22-Spark算子Transformations和Action使用大全(Transformations章(一))
- spark学习-23-Spark算子Transformations和Action使用大全(Transformations章(二))
- spark-DataFrame学习记录-[2]解决spark-dataframe的JOIN操作之后产生重复列(Reference '***' is ambiguous问题解决)
- spark dataFrame 新增一列函数withColumn
- Spark的DataFrame的窗口函数使用
- Spark SQL和DataFrame的学习总结
- spark-DataFrame学习记录-[1]基础部分
- 纯CSS实现select的placeholder效果
- PREV-5 错误票据
- 12.03周日
- object_detection API论文Speed/accuracy trade-offs for...的详细中文翻译
- 11.优化服务器设置
- 通过例子学习spark dataframe -- transformations函数(2)
- 6.12
- python从控制台接收输入创建二叉树
- 挖掘布尔关联法则发现频繁项集的Apriori算法
- Javascript 异步编程方法
- 第五届图灵杯1869
- UVa 11401 Triangle Countin(找规律)
- Lock锁
- jsp 之 入门 jsp代码块