spark dataframe实战(持续更新)

spark dataframe实战

说明:该文基于spark-2.0+

dataframe介绍

dataframe是dataset的行的集合。

Dataset是分布式数据集合。Dataset是Spark 1.6+中添加的一个新接口,它提供了RDD的很多优点。 (强类型化,使用强大的lambda函数的功能),以及Spark SQL优化执行引擎的优点。数据集可以从JVM对象构建,然后使用函数转换(map,flatMap,filter等)进行操作。数据集API可用于Scala和Java。
Python不支持数据集API。但是由于Python的动态特性,数据集API的许多优点已经可用(即,您可以通过自然的row.columnName名称来访问行的字段)。R的情况是相似的。

一个DataFrame是一个数据集组织成命名列。它在概念上等同于关系数据库中的表或R / Python中的(dataframe)数据框,但是在实现引擎层面有更多的优化。
DataFrame可以从各种各样的源构建,例如:结构化数据文件,Hive中的表,外部数据库或现有的RDD。DataFrame API可用于Scala,Java,Python和R.在Scala和Java中,DataFrame由行数据集表示。在Scala API中,DataFrame只是Dataset [Row]的类型别名。而在Java API中,用户需要使用Dataset 来表示一个DataFrame。

在整篇文档中,我们经常将Scala / Java数据集作为DataFrames。

sparkSession

在spark-2.0以后,引入了sparkSession来对资源进行管理。包括管理spark Context等。创建一个sparkSession的代码如下。

import org.apache.spark.sql.SparkSession

val spark = SparkSession.builder().appName("Spark SQL basic example").config("spark.some.config.option", "some-value").getOrCreate()

// For implicit conversions like converting RDDs to DataFrames
import spark.implicits._

创建Dataframe

通过toDs来创建dataframe

val ds = Seq(1, 2, 3).toDS()

加载文件数据创建

dataframe可以加载各种格式的文件。
下面的例子会通过一个数据文件进行讲解,该文件的内容如下:

$ hadoop fs -cat /user/zxh/csvdata/csvdata
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
  • 加载csv文件
    注意:spark是开始创建的sparkSession实体。
val spark = SparkSession.builder().appName("Spark SQL basic example").config("spark.some.config.option", "some-value").getOrCreate()
import spark.implicits._
val df = spark.read.csv("/user/hadoop/csvdata/csvdata")

scala> val df = spark.read.option("header",true).csv("/user/hadoop/csvdata/csvdata")
df: org.apache.spark.sql.DataFrame = [id: string, name: string ... 2 more fields]

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|
+---+----+-------+-----+
  • 加载json文件
$ hadoop fs -cat /user/zxh/jsondata/jsondata
{ "name":"Yin", "address":{ "city":"Columbus", "state":"Ohio" }}

scala> val df = spark.read.json("/user/zxh/jsondata/jsondata")
df: org.apache.spark.sql.DataFrame = [address: struct<city: string, state: string>, name: string]

scala> df.show()
+---------------+----+
|        address|name|
+---------------+----+
|[Columbus,Ohio]| Yin|
+---------------+----+
  • 加载parquet文件
val peopleDF = spark.read.format("json").load("examples/src/main/resources/people.json")
peopleDF.select("name", "age").write.format("parquet").save("namesAndAges.parquet")
val sqlDF = spark.sql("SELECT * FROM parquet.`examples/src/main/resources/users.parquet`")
val usersDF = spark.read.load("examples/src/main/resources/users.parquet")
usersDF.select("name", "favorite_color").write.save("namesAndFavColors.parquet")

从JDBC加载数据

  • 通过JDBC读取数据
// Note: JDBC loading and saving can be achieved via either the load/save or jdbc methods
// Loading data from a JDBC source
val jdbcDF = spark.read
  .format("jdbc")
  .option("url", "jdbc:postgresql:dbserver")
  .option("dbtable", "schema.tablename")
  .option("user", "username")
  .option("password", "password")
  .load()

val connectionProperties = new Properties()
connectionProperties.put("user", "username")
connectionProperties.put("password", "password")
val jdbcDF2 = spark.read
  .jdbc("jdbc:postgresql:dbserver", "schema.tablename", connectionProperties)

// Saving data to a JDBC source
jdbcDF.write
  .format("jdbc")
  .option("url", "jdbc:postgresql:dbserver")
  .option("dbtable", "schema.tablename")
  .option("user", "username")
  .option("password", "password")
  .save()

jdbcDF2.write
  .jdbc("jdbc:postgresql:dbserver", "schema.tablename", connectionProperties)

// Specifying create table column data types on write
jdbcDF.write
  .option("createTableColumnTypes", "name CHAR(64), comments VARCHAR(1024)")
  .jdbc("jdbc:postgresql:dbserver", "schema.tablename", connectionProperties)

操作Dataframe

  • 为dataframe设置新的字段名(列名)
scala> val newNames = Seq("id1", "name1", "score1")
newNames: Seq[String] = List(id1, name1, score1)

scala> val dfRenamed = df.toDF(newNames: _*)
dfRenamed: org.apache.spark.sql.DataFrame = [id1: string, name1: string ... 1 more field]

scala> dfRenamed.show()
+---+-----+------+
|id1|name1|score1|
+---+-----+------+
|  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|
+---+-----+------+
  • 添加一个新列:通过其他列的值来添加
    为了添加一列,我们可以使用withColumn函数来
scala> val df2 = df.withColumn("newscore", df("score")+50)
df2: org.apache.spark.sql.DataFrame = [id: string, name: string ... 2 more fields]

scala> df2.show()
+---+----+-----+--------+
| id|name|score|newscore|
+---+----+-----+--------+
|  1|  n1|   10|    60.0|
|  2|  n2|   20|    70.0|
|  3|  n3|   30|    80.0|
|  4|  n4|   40|    90.0|
|  5|  n5|   50|   100.0|
|  6|  n6|   60|   110.0|
|  7|  n6|   60|   110.0|
|  8|  n8|   60|   110.0|
|  8|  n9|   60|   110.0|
|  9|  n9|   60|   110.0|
+---+----+-----+--------+
  • 条件去重
    通过select可以选择要返回的列,通过where函数可以对列进行筛选。在使用distinct函数去重。
scala> val df3 = df.select("name").where($"score">50).distinct()
df3: org.apache.spark.sql.Dataset[org.apache.spark.sql.Row] = [name: string]

scala> df3.show()
+----+
|name|
+----+
|  n8|
|  n9|
|  n6|
+----+
  • 根据多列的值去重
    可以看到以下代码按name,score这两列的值进行去重。
scala> val df3 = df.select("name", "score").where($"score">50).distinct()
df3: org.apache.spark.sql.Dataset[org.apache.spark.sql.Row] = [name: string, score: string]

scala> df3.show()
+----+-----+
|name|score|
+----+-----+
|  n9|   60|
|  n8|   60|
|  n6|   60|
+----+-----+
  • 如何把dataframe的整数列转换成字符串

以下代码把df的col1列的值转换成字符串类型:

var df2 = df.withColumn("col1", df("col1").cast("string"))
  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值