PySpark(5)创建DataFrame

# 数据准备
columns = ["language","users_count"]
data = [("Java", "20000"), ("Python", "100000"), ("Scala", "3000")]
  •  1. Create PySpark DataFrame from an existing RDD.
'''
1. Create PySpark DataFrame from an existing RDD.
'''
# 首先创建一个需要的RDD
spark = SparkSession.builder.appName('SparkByExamples.com').getOrCreate()
rdd = spark.sparkContext.parallelize(data)
# 1.1 Using toDF() function: RDD 转化成 DataFrame, 如果RDD没有Schema,DataFrame会创建默认的列名"_1","_2"等等.
dfFromRDD1 = rdd.toDF()
dfFromRDD1.printSchema()
dfFromRDD1.show()
# 如果需要自定义列名,可在调用toDF()方法时,以列名作为参数传入
dfFromRDD1 = rdd.toDF(columns)
dfFromRDD1.printSchema()
dfFromRDD1.show()

# 1.2 Using createDataFrame() from SparkSession : 用createDataFrame()方法,以RDD作为参数创建DataFrame,连接.toDF(*columns)创建列名.
dfFromRDD1 = spark.createDataFrame(rdd).toDF(*columns)
dfFromRDD1.printSchema()
dfFromRDD1.show()
  •  2. Create DataFrame from List Collection
'''
2. Create DataFrame from List Collection
'''
# 2.1 Using createDataFrame() from SparkSession
dfFromData2 = spark.createDataFrame(data).toDF(*columns)
dfFromData2.printSchema()
dfFromData2.show()

# 2.2 Using createDataFrame() with the Row type
# 需要将list对象[(), (), ...],转换成[Row1, Row2, ...]
rowData = map(lambda x: Row(*x), data)
# print(list(rowData)[0])
dfFromData3 = spark.createDataFrame(rowData,columns)
dfFromData3.printSchema()
dfFromData3.show()

# 2.3 Create DataFrame with schema
# 如果你想指定列名及其类型,需要创建StructType schema并分配
data2 = [("James", "", "Smith", "36636", "M", 3000),
         ("Michael", "Rose", "", "40288", "M", 4000),
         ("Robert", "", "Williams", "42114", "M", 4000),
         ("Maria", "Anne", "Jones", "39192", "F", 4000),
         ("Jen", "Mary", "Brown", "", "F", -1)
         ]

schema = StructType([ \
    StructField("firstname", StringType(), True), \
    StructField("middlename", StringType(), True), \
    StructField("lastname", StringType(), True), \
    StructField("id", StringType(), True), \
    StructField("gender", StringType(), True), \
    StructField("salary", IntegerType(), True) \
    ])

df = spark.createDataFrame(data=data2, schema=schema)
df.printSchema()
df.show(truncate=False)
  •  3. Create DataFrame from Data sources
'''
3. Create DataFrame from Data sources
'''
# 从数据源文件(例如CSV,文本,JSON,XML等)创建DataFrame.
# 3.1 Creating DataFrame from CSV
df2 = spark.read.csv("/src/resources/file.csv")

# 3.2. Creating from text (TXT) file
df2 = spark.read.text("/src/resources/file.txt")

# 3.3. Creating from JSON file
df2 = spark.read.json("/src/resources/file.json")
  • 4. Other sources (Avro, Parquet, ORC, Kafka)
# 4.1 PySpark read and write Parquet File
# Pyspark SQL提供了将Parquet文件读入DataFrame并将DataFrame写入Parquet文件的方法,
# DataFrameReader和DataFrameWriter的parquet()函数分别用于读取和写入/创建Parquet文件。
# (1) how to write and read parquet files in PySpark
dfFromRDD1 = spark.createDataFrame(rdd).toDF(*columns)
df = dfFromRDD1
df.write.parquet("people.parquet")
parDF1=spark.read.parquet("people.parquet")
'''
在详细说明之前,首先让我们了解什么是Parquet文件及其相对于CSV,JSON和其他文本文件格式的优势。
 Apache Parquet文件是一种列式存储格式,可用于Hadoop生态系统中的任何项目,而不管选择数据处理框架,数据模型还是编程语言。
查询列式存储时,它会非常快地跳过无关数据,从而加快查询执行速度。 结果,与面向行的数据库相比,聚合查询消耗的时间更少。

它能够支持高级嵌套数据结构。Parquet支持有效的压缩选项和编码方案。
Pyspark SQL提供了对读取和写入Parquet文件的支持,这些文件可自动捕获原始数据的架构,而且平均可将数据存储量减少75%。 
Pyspark默认情况下在其库中支持Parquet,因此我们不需要添加任何依赖库。
'''
# 分析Parquet文件,准备数据,首先用list创建df对象,再将对象转换成Parquet文件
# data =[("James ","","Smith","36636","M",3000),
#               ("Michael ","Rose","","40288","M",4000),
#               ("Robert ","","Williams","42114","M",4000),
#               ("Maria ","Anne","Jones","39192","F",4000),
#               ("Jen","Mary","Brown","","F",-1)]
# columns=["firstname","middlename","lastname","dob","gender","salary"]
# df=spark.createDataFrame(data,columns)
# df.write.parquet("people.parquet")
# # Pyspark Read Parquet file into DataFrame
# parDF=spark.read.parquet("people.parquet")

# (2)Append or Overwrite an existing Parquet file
# 可以使用append模式来添加新的df对象到parquet文件中去
# 可以使用overwrite模式去用新的df对象覆盖原来parquet文件内容
# df.write.mode('append').parquet("people.parquet")
# df.write.mode('overwrite').parquet("people.parquet")

# (3)Executing SQL queries DataFrame
# 对parquet文件创建一个临时视图,以便能执行SQL查询;首先将parquet文件转换成DataFrame对象,再createOrReplaceTempView方法
# parqDF=spark.read.parquet("people.parquet")
# parqDF.createOrReplaceTempView("ParquetTable")
# parkSQL = spark.sql("select * from ParquetTable where salary >= 4000 ").show()

# (4) Creating a table on Parquet file
# 直接使用SQL语句,对Parquet file创建临时视图;
# spark.sql("CREATE TEMPORARY VIEW PERSON USING parquet OPTIONS (path \"people.parquet\")")
# spark.sql("SELECT * FROM PERSON").show()

# (5)Create Parquet partition file
# 当我们在PERSON表上执行特定查询时,它会扫描所有行并将结果返回。 这类似于传统的数据库查询执行。
# 在PySpark中,我们可以使用partitionBy()方法对数据进行分区,从而以优化的方式改善查询执行。
# df.write.partitionBy("gender","salary").mode("overwrite").parquet("people2.parquet")

# (6)(检索)Retrieving from a partitioned Parquet file
# 读取分区文件:将文件中gender=M,即性别是男性的行查询出来;
# parDF2=spark.read.parquet("people2.parquet/gender=M")
# parDF2.show(truncate=False)

# (7)Creating a table on Partitioned Parquet file
# 在分区文件上的查询速度,要好于没有分区的文件
# spark.sql("CREATE TEMPORARY VIEW PERSON2 USING parquet OPTIONS (path \"people2.parquet/gender=F\")")
# spark.sql("SELECT * FROM PERSON2" ).show()
'''
我们已经学习了如何从PySpark DataFrame写入Parquet文件以及如何将Parquet文件读取到DataFrame并创建视图/表以执行SQL查询。 
还介绍了如何对Parquet文件进行分区以提高性能。
'''
# 4.2 Read & Write Avro files using Spark DataFrame
'''
首先介绍Avro是什么及其优点
Avro支持两种序列化编码方式:二进制编码和JSON编码。使用二进制编码会高效序列化,并且序列化后得到的结果会比较小;而JSON一般用于调试系统或是基于WEB的应用。
Apache Avro是针对Hadoop项目的开源,基于行的数据序列化和数据交换框架,最初是由databricks作为开放源代码库开发的,它支持以Avro文件格式读写数据。 
它主要用于Apache Spark,尤其是用于基于Kafka的数据管道。 将Avro数据存储在文件中时,其架构也会随之存储,因此以后任何程序都可以处理文件。
它具有在不同的基于Hadoop的项目之间序列化和交换大数据的功能。 它以紧凑的二进制格式序列化数据,并且模式为JSON格式,用于定义字段名称和数据类型。
它与Thrift和Protocol Buffer类似,但是不需要代码生成,因为它的数据始终带有一个架构,该架构允许在不生成代码的情况下完全处理该数据。 
与其他序列化系统相比,这是最大的优势之一。

支持复杂的数据结构,如数组,地图,地图数组和数组元素地图。
一种紧凑的二进制序列化格式,可在传输数据时快速提供。
基于行的数据序列化系统。
支持多国语言,意味着一种语言编写的数据可以被不同的语言读取。
读取或写入数据文件不需要代码生成。
与动态语言的简单集成。
'''
# 导包,准备数据
from pyspark.sql import avro
spark = SparkSession.builder.appName('SparkByExamples.com')\
    .config('spark.jars.packages', 'org.apache.spark:spark-avro_2.12:2.4.4').getOrCreate()

# data =[("James ","","Smith","36636","M",3000),
#               ("Michael ","Rose","","40288","M",4000),
#               ("Robert ","","Williams","42114","M",4000),
#               ("Maria ","Anne","Jones","39192","F",4000),
#               ("Jen","Mary","Brown","","F",-1)]
# columns=["firstname","middlename","lastname","dob","gender","salary"]
# df=spark.createDataFrame(data,columns)

# (1)Write Spark DataFrame to Avro Data File
# df.write.format("avro").save("person.avro")

# (2) Read Avro Data File to Spark DataFrame
# personDF= spark.read.format("avro").load("person.avro")
# personDF.show()

# (3) Writing Avro Partition Data
# 文件分区,提高查询性能
# data = [("James ","","Smith",2018,1,"M",3000),
#       ("Michael ","Rose","",2010,3,"M",4000),
#       ("Robert ","","Williams",2010,3,"M",4000),
#       ("Maria ","Anne","Jones",2005,5,"F",4000),
#       ("Jen","Mary","Brown",2010,7,"",-1)]
# columns = ["firstname", "middlename", "lastname", "dob_year",
#  "dob_month", "gender", "salary"]
# df=spark.createDataFrame(data,columns)
# df.write.partitionBy("dob_year","dob_month").format("avro").save("person_partition.avro")

# (4) Reading Avro Partition Data
# 注意:where中的写法
# spark.read.format("avro").load("person_partition.avro").where("dob_year == 2010").show()


# (5) Using Avro Schema
'''
Avro模式通常以.avsc扩展名定义,文件格式为JSON。 将在person.avsc文件中的架构下方存储,并在读取Avro文件时使用option()提供此文件。 
该架构为Avro文件的结构提供了字段名称和数据类型。
'''

# (6) Using Avro with Spark SQL
spark.sql("CREATE TEMPORARY VIEW PERSON USING avro OPTIONS (path \"person.avro\")")
spark.sql("SELECT * FROM PERSON").show()
'''
我们已经看到了有关如何编写Avro数据文件以及如何使用Spark DataFrame进行读取的示例。 
另外,我还介绍了Avro分区的使用方法以及在读取Avro文件时如何改进分区。 
'''

 

 

 

 

你可能感兴趣的:(spark)