通过例子学习spark dataframe -- transformations函数(1)
来源:互联网 发布:如何查看淘宝客佣金 编辑:程序博客网 时间:2024/06/08 05:26
- 说明
- dataframe类型化函数Typed transformations
- coalesce
- dropDuplicates
- where
- sort
- select
- distinct
- intersect
- union
- limit
- groupByKey
- map
- mapPartitions
说明
transformations函数分为两类:
* Typed transformations
这类函数的返回值一般都是dataset,也就是说不会改变原来的数据集的类型。
* Untyped transformations
这类函数的返回值,会根据不同的函数返回不同的类型。
本文讲解的是第一类的函数,也就是说返回的类型基本上是相同的都是dataset。
本文的所有例子,都是基于spark-2.1进行操作。
本文的所有例子,都是基于以下简单的csv数据集进行讲解:
scala> import org.apache.spark.sql.SparkSessionimport org.apache.spark.sql.SparkSessionscala> val spark = SparkSession.builder().appName("Spark SQL basic example").config("spark.some.config.option", "some-value").getOrCreate()17/11/28 07:08:49 WARN SparkSession$Builder: Using an existing SparkSession; some configuration may not take effect.spark: org.apache.spark.sql.SparkSession = org.apache.spark.sql.SparkSession@c45908cscala> import spark.implicits._import spark.implicits._scala> val df = spark.read.format("csv").option("header", true).load("/user/hadoop/csvdata/csvdata")df: org.apache.spark.sql.DataFrame = [id: string, name: string ... 1 more field]scala> df.show()+---+----+-----+| id|name|score|+---+----+-----+| 1| n1| 10|| 2| n2| 20|| 3| n3| 30|| 4| n4| 40|| 5| n5| 50|| 6| n6| 60|| 7| n6| 60|| 8| n8| 60|| 8| n9| 60|| 9| n9| 60|+---+----+-----+
dataframe类型化函数(Typed transformations)
说明:这些函数最后返回的都是一个类型,也就是Dataset[T]。这类dataframe是dataset的行集合。
coalesce
功能
若你需要更少的分区,可以通过该函数来得到具有确定分区数的新的数据集。如果请求更多的分区,它将保持在当前的分区数量。类似于在RDD上定义的合并,该操作导致狭窄的依赖性,例如,如果你从1000个分区转到100个分区,那么就不会有shuffle,而是100个新分区中的每一个都会声称当前分区有10个。
但是,如果您正在进行激烈的合并,例如到numPartitions = 1,这可能会导致你的计算发生在比你喜欢的节点更少的节点上(例如numPartitions = 1的情况下是一个节点)。为了避免这种情况,您可以调用repartition。这将增加一个shuffle步骤,但意味着当前的上游分区将并行执行(无论当前分区是什么)。原型
def coalesce(numPartitions: Int): Dataset[T]
- 例子1
从下面的代码可以看出,新的dataframe分区数据减少了。
scala> val df3 = spark.read.format("csv").option("header", false).load("/warehouse/spark/testdata/")df3: org.apache.spark.sql.DataFrame = [_c0: string, _c1: string ... 34 more fields]scala> df3.rdd.partitions.lengthres10: Int = 15scala> df3.coalesce(10)res11: org.apache.spark.sql.Dataset[org.apache.spark.sql.Row] = [_c0: string, _c1: string ... 34 more fields]scala> df3.rdd.partitions.lengthres12: Int = 15scala> val df4 = df3.coalesce(10)df4: org.apache.spark.sql.Dataset[org.apache.spark.sql.Row] = [_c0: string, _c1: string ... 34 more fields]scala> df4.rdd.partitions.lengthres13: Int = 10
dropDuplicates
功能
按照某个字段去重。原型
def dropDuplicates(colNames: Array[String]): Dataset[T] def dropDuplicates(col1: String, cols: String*): Dataset[T] def dropDuplicates(colNames: Seq[String]): Dataset[T] // 按所有字段去重def dropDuplicates(): Dataset[T]
- 例子1
scala> df.sort().dropDuplicates("id").show()+---+----+-----+| id|name|score|+---+----+-----+| 7| n6| 60|| 1| n1| 10|| 6| n6| 60|| 4| n4| 40|| 8| n8| 60|| 3| n3| 30|| 2| n2| 20|| 5| n5| 50|| 9| n9| 60|+---+----+-----+
where
功能
对dataframe满足条件的列进行过滤。原型
where的原型有两种:
def where(conditionExpr: String): Dataset[T] def where(condition: Column): Dataset[T]
通过以上原型,可以看出,一种是直接添加字符串,一种是通过列来对数据进行过滤。
- 例子1
scala> val df3 = df.select("id", "name").where($"score">50).distinct()df3: org.apache.spark.sql.Dataset[org.apache.spark.sql.Row] = [id: string, name: string]scala> df3.show()+---+----+ | id|name|+---+----+| 7| n6|| 9| n9|| 6| n6|| 8| n8|| 8| n9|+---+----+
以上例子也可以写成下面的形式,结果是一样的:
val df3 = df.select("name", "score").where("score>50").distinct()
- 例子2
添加多个条件进行过滤。
scala> val df3 = df.select("name", "score").where("score>10 and score<50").distinct()df3: org.apache.spark.sql.Dataset[org.apache.spark.sql.Row] = [name: string, score: string]scala> df3.show()+----+-----+|name|score|+----+-----+| n4| 40|| n2| 20|| n3| 30|+----+-----+
也可以写成以下形式:
val df3 = df.select("name", "score").where($"score">10 && $"score" > 50).distinct()
sort
功能
可以根据特定的列或排序表达式进行排序。同时还可以指定按升序还是降序排序。
注意:默认情况下,sort是按升序排列的。函数原型
def sort(sortExprs: Column*): Dataset[T] def sort(sortCol: String, sortCols: String*): Dataset[T]
- 例子1
按score降序排列以下记录。
scala> val df3 = df.select("id","name", "score").where("score<50").sort($"score".desc)df3: org.apache.spark.sql.Dataset[org.apache.spark.sql.Row] = [id: string, name: string ... 1 more field]// 可以看到记录已按score成降序排列scala> df3.show()+---+----+-----+| id|name|score|+---+----+-----+| 4| n4| 40|| 3| n3| 30|| 2| n2| 20|| 1| n1| 10|+---+----+-----+
- 例子2
按两列进行排序。
scala> val df3 = df.select("id","name", "score").where("score>50").sort($"id".desc, $"score".desc)df3: org.apache.spark.sql.Dataset[org.apache.spark.sql.Row] = [id: string, name: string ... 1 more field]scala> df3.show()+---+----+-----+| id|name|score|+---+----+-----+| 9| n9| 60|| 8| n9| 60|| 8| n8| 60|| 7| n6| 60|| 6| n6| 60|+---+----+-----+
select
功能
选择需要返回的列,并可以对列进行一些操作。原型
def select[U1, U2, U3](c1: TypedColumn[T, U1], c2: TypedColumn[T, U2], c3: TypedColumn[T, U3]): Dataset[(U1, U2, U3)] def select[U1, U2](c1: TypedColumn[T, U1], c2: TypedColumn[T, U2]): Dataset[(U1, U2)] def select[U1](c1: TypedColumn[T, U1]): Dataset[U1]
- 例子1:选取列
scala> val df3 = df.select("id", "name").limit(2)df3: org.apache.spark.sql.Dataset[org.apache.spark.sql.Row] = [id: string, name: string]scala> df3.show()+---+----+| id|name|+---+----+| 1| n1|| 2| n2|+---+----+
- 例子2:选取列时,为列选取别名
scala> val df2 = df.select($"id" as "id2")df2: org.apache.spark.sql.DataFrame = [id2: string]
- 例子3:选取列时,改变列的值和列的数据类型
scala> val df4 = df.select($"id", expr("score+10").as[Double] as "newscore").limit(2)df4: org.apache.spark.sql.Dataset[org.apache.spark.sql.Row] = [id: string, newscore: double]scala> df4.show()+---+--------+| id|newscore|+---+--------+| 1| 20.0|| 2| 30.0|+---+--------+
distinct
功能说明
对数据集去重。函数原型
def distinct(): Dataset[T]
- 例子1
scala> df.select("id").distinct().sort("id").collect()res5: Array[org.apache.spark.sql.Row] = Array([1], [2], [3], [4], [5], [6], [7], [8], [9])
intersect
功能说明
对两个数据集取交集,返回两个数据集共有的行。函数原型
def intersect(other: Dataset[T]): Dataset[T]
- 例子1
scala> val df2 = df.where($"score">50)df2: org.apache.spark.sql.Dataset[org.apache.spark.sql.Row] = [id: string, name: string ... 1 more field]scala> df2.show()+---+----+-----+| id|name|score|+---+----+-----+| 6| n6| 60|| 7| n6| 60|| 8| n8| 60|| 8| n9| 60|| 9| n9| 60|+---+----+-----+scala> val df3 = df.intersect(df2)df3: org.apache.spark.sql.Dataset[org.apache.spark.sql.Row] = [id: string, name: string ... 1 more field]scala> df3.sort("id").show()+---+----+-----+| id|name|score|+---+----+-----+| 6| n6| 60|| 7| n6| 60|| 8| n8| 60|| 8| n9| 60|| 9| n9| 60|+---+----+-----+
union
函数功能
合并两个数据集。注意:合并的两个数据集(dataset)的列数必须相同,否则会报错。函数原型
def union(other: Dataset[T]): Dataset[T]
- 例子1
scala> val df4 = df.union(df3)df4: org.apache.spark.sql.Dataset[org.apache.spark.sql.Row] = [id: string, name: string ... 1 more field]scala> df4.show()+---+----+-----+| id|name|score|+---+----+-----+| 1| n1| 10|| 2| n2| 20|| 3| n3| 30|| 4| n4| 40|| 5| n5| 50|| 6| n6| 60|| 7| n6| 60|| 8| n8| 60|| 8| n9| 60|| 9| n9| 60|| 8| n8| 60|| 7| n6| 60|| 9| n9| 60|| 6| n6| 60|| 8| n9| 60|+---+----+-----+
limit
功能
返回数据集的前n行,不同于head的是:limit返回的是一个dataset,而head返回的是array。函数原型
def limit(n: Int): Dataset[T]
- 例子1
scala> val df2 = df.limit(2)df2: org.apache.spark.sql.Dataset[org.apache.spark.sql.Row] = [id: string, name: string ... 1 more field]scala> df2.show()+---+----+-----+| id|name|score|+---+----+-----+| 1| n1| 10|| 2| n2| 20|+---+----+-----+
groupByKey
功能
根据特定的函数对数据进行聚合。然后返回一个KeyValueGroupedDataset类型的dataset。
注意:该函数会通过HashPartitioner的方式把数据重按key的值新分区,把相同key的值分到同一分区中,这样在大部分的情况下会导致shuffle。完成这个过程后,会在本地的分区上执行aggregation。函数原型
// for javadef groupByKey[K](func: MapFunction[T, K], encoder: Encoder[K]): KeyValueGroupedDataset[K, T]// for scaladef groupByKey[K](func: (T) => K)(implicit arg0: Encoder[K]): KeyValueGroupedDataset[K, T]
- 例子1
scala> df.groupByKey(l=>l.getString(0)).count.show()+-----+--------+|value|count(1)|+-----+--------+| 7| 1|| 1| 1|| 6| 1|| 4| 1|| 8| 2|| 3| 1|| 2| 1|| 5| 1|| 9| 1|+-----+--------+
- 例子2
scala> df.groupByKey(r=>r.getString(0)).mapValues(r=>r.getString(1)).reduceGroups( (id, name) => (id+","+name)).show()+-----+----------------------------------+|value|ReduceAggregator(java.lang.String)|+-----+----------------------------------+| 7| n6|| 1| n1|| 6| n6|| 4| n4|| 8| n8,n9|| 3| n3|| 2| n2|| 5| n5|| 9| n9|+-----+----------------------------------+
map
功能
对数据集上的每一行使用函数func进行处理,并返回一个新的dataset。
注意:dataframe的map和rdd的不同,这里需要返回一个新的dataset。函数原型
// for javadef map[U](func: MapFunction[T, U], encoder: Encoder[U]): Dataset[U]// for scaladef map[U](func: (T) ⇒ U)(implicit arg0: Encoder[U]): Dataset[U]
- 例子1
scala> val df2 = df.map(r=>(r.getString(0),r.getString(1))).limit(2)df2: org.apache.spark.sql.Dataset[(String, String)] = [_1: string, _2: string]scala> df2.show()+---+---+| _1| _2|+---+---+| 1| n1|| 2| n2|+---+---+
mapPartitions
功能
在数据集的每个分区上使用函数func函数原型
def mapPartitions[U](f: MapPartitionsFunction[T, U], encoder: Encoder[U]): Dataset[U]def mapPartitions[U](func: (Iterator[T]) ⇒ Iterator[U])(implicit arg0: Encoder[U]): Dataset[U]
- 通过例子学习spark dataframe -- transformations函数(1)
- 通过例子学习spark dataframe -- transformations函数(2)
- 通过例子学习spark rdd--Transformations函数
- 通过例子学习spark dataframe--基础函数和Action函数
- 通过例子学习spark rdd--Action函数
- spark dataframe函数编程
- spark-DataFrame学习记录-[1]基础部分
- 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 新增一列函数withColumn
- Spark的DataFrame的窗口函数使用
- Spark SQL和DataFrame的学习总结
- Spark SQL和DataFrame的学习总结
- HDOJ 2566 统计硬币 (水)
- servlet写文件时发生错误
- HDU 5698:瞬间移动(排列组合)
- 1053. Path of Equal Weight (30)
- andriod——Retrofit+Fresco+MVP网络获取数据
- 通过例子学习spark dataframe -- transformations函数(1)
- mysql半同步复制
- 机房收费系统——上机操作
- 图的遍历(DFS)
- 末尾0的个数
- 人伦是否适用于AI?
- 线性分式变换(linear fractional transformation)
- LeetCode 334. Increasing Triplet Subsequence
- 2017.12.3第十四周周总结