Spark之两个DataFrame的操作
1、inner
2、outer
3、left_outer
4、right_outer
5、left_semi
6、left_anti
7、union
注:这里只采用DF的操作语法,至于将DF创建成视图使用SQL的语法这里就不介绍了。
一、创建DF备用
(1)手工输入几条测试数据,快速构造一个测试DataFrame备用
#python
#手动输入几条数据,构造一个简单的测试DataFrame
df1 = spark.createDataFrame([
(500, "Vice President","hello"),
(250, "PMC Member","hi"),
(100, "Contributor","salut")]).toDF("col1", "col2","col3")
(2)从文件中读取(自定义schema, 自动推断schema/意味着header = true)
#in python
hdfs_csv_file = "hdfs://path/to/file.csv"
from pyspark.sql.types import StructField, StructType, StringType, IntegerType
myManualSchema = StructType([
StructField("col1", IntegerType(), True),
StructField("col2", StringType(), True),
StructField("col3", StringType(), True)
])
df2 = spark.read.format("csv").schema(myManualSchema).load(hdfs_csv_file)
(3)创建空的(自定义schema, 复制已有schema)
#当新建的DataFrame结构与已知的DataFrame结构一样的时候,可以直接调用另一个DF.schema
df0 = spark.createDataFrame(spark.sparkContext.emptyRDD(), df2.schema)
二、两个DF的关联( 使用DF语言的操作)inner、outer、left_outer、right_outer、left_semi、left_anti、union
1、内关联 inner
#1、df1和df2做内关联,关联列为一个:"col1"。两个DF都有要关联的列,且列名相同
df3 = df1.join(df2,["col1"],"inner")
df3 = df1.join(df2,["col1"]) #inner join 是默认的join方式,所以可以省略这个参数
#2、df1和df2做内关联,关联列为一个:"col1"。两个DF都有要关联的列,但列名不同
df3 = df1.join(df2,df1["col1"] == df2["id"],"inner")
#3、df1和df2做内关联,关联列为多个:"col1","col2","col3"。两个DF都有要关联的列,且列名相同
df3 = df1.join(df2,["col1","col2","col3"],"inner")
#4、df1和df2做内关联,关联列为多个:"col1","col2","col3"。两个DF都有要关联的列,但列名不同
df3 = df1.join(df2,???,"inner")
2、外关联(即全关联) outer
#1、df1和df2做外关联,关联列为一个:"col1"。两个DF都有要关联的列,且列名相同
df3 = df1.join(df2,["col1"],"outer")
#2、df1和df2做外关联,关联列为多个:"col1","col2","col3"。两个DF都有要关联的列,且列名相同
df3 = df1.join(df2,["col1","col2","col3"],"outer")
3、左关联 left_outer
#1、df1和df2做左外关联,关联列为一个:"col1"。两个DF都有要关联的列,且列名相同
df3 = df1.join(df2,["col1"],"left_outer")
#2、df1和df2做左外关联,关联列为多个:"col1","col2","col3"。两个DF都有要关联的列,且列名相同
df3 = df1.join(df2,["col1","col2","col3"],"left_outer")
4、右关联 right_outer
#1、df1和df2做右外关联,关联列为一个:"col1"。两个DF都有要关联的列,且列名相同
df3 = df1.join(df2,["col1"],"right_outer")
#2、df1和df2做右外关联,关联列为多个:"col1","col2","col3"。两个DF都有要关联的列,且列名相同
df3 = df1.join(df2,["col1","col2","col3"],"right_outer")
5、左半关联 left_semi
左半关联相当于SQL中的IN 函数,快速判断左边列是否在右边表中,在就保留行,不在就不保留这行数据。
或者像其他解释说的,右边的表相当于filter过滤条件。
#in python
#1、df1和df2做左半关联,关联列为一个:"col1"。两个DF都有要关联的列,且列名相同
df3 = df1.join(df2,["col1"],"left_semi")
6、左反关联 left_anti
左反关联相当于SQL中的NOT IN 函数,快速判断左边列是否在右边表中,在就不保留行,不在就保留这行数据。 这是跟left_semi 完全相反的函数。
#in python
#1、df1和df2做左反关联,关联列为一个:"col1"。两个DF都有要关联的列,且列名相同
df3 = df1.join(df2,["col1"],"left_anti")
7、两个DF 做union合并
两个DataFrame做合并的时候要确保它们具有相同的schema和列数,否则会失败。
#in python
df3 = df1.union(df2)
问题:如果df1 和df2 都有三列相同列名的列:col1 、col2 、col3, 而我们关联的时候仅使用col1做为两个DF的关联列,那么生成的DF会有几列col2、col3? 如果列名重复了,又该怎么处理呢?
关于DataFrame的复杂结构的关联操作,请参考 博文:
三、将关联操作后的DF排序、去重后写出
1、DF排序 sort 、orderBy
#in python
#1、 orderBy排序, 按照列"col2","col1" 来排序
df2.orderBy("col2","col1")
#2、sort排序
df2.sort("col2","col1")
2、DF去重 distinct
df.select("col1", "col2").distinct()
3、DF写出到HDFS的CSV文件/TXT文件中
df2.write.format("csv").mode("overwrite").option("sep",",").option("header",True).save(hdfs_result)
4、DF写出到ES或CK或SQL等