![](/img/trans.png)
[英]Convert spark Dataframe with schema to dataframe of json String
[英]Convert Spark DataFrame schema to new schema
我有多个从不同来源读取的spark作业,它们有不同的模式但它们非常接近,我想要做的就是将它们全部写入同一个Redshift表中,所以我需要统一所有的DataFrame模式,什么是最好的方法吗?
假设第一个输入数据的模式如下:
val schema1 = StructType(Seq(
StructField("date", DateType),
StructField("campaign_id", StringType),
StructField("campaign_name", StringType),
StructField("platform", StringType),
StructField("country", StringType),
StructField("views", DoubleType),
StructField("installs", DoubleType),
StructField("spend", DoubleType)
))
seconf inout source的Schema如下:
val schema2 = StructType(Seq(
StructField("date", DateType),
StructField("creator_id", StringType),
StructField("creator_name", StringType),
StructField("platform", StringType),
StructField("views", DoubleType),
StructField("installs", DoubleType),
StructField("spend", DoubleType),
StructField("ecpm", DoubleType)
))
表架构(预期的统一数据框架):
val finalSchema = StructType(Seq(
StructField("date", DateType),
StructField("account_name", StringType),
StructField("adset_id", StringType),
StructField("adset_name", StringType),
StructField("campaign_id", StringType),
StructField("campaign_name", StringType),
StructField("pub_id", StringType),
StructField("pub_name", StringType),
StructField("creative_id", StringType),
StructField("creative_name", StringType),
StructField("platform", StringType),
StructField("install_source", StringType),
StructField("views", IntegerType),
StructField("clicks", IntegerType),
StructField("installs", IntegerType),
StructField("cost", DoubleType)
))
正如您在最终模式中看到的那样,我有一些列可能不在输入模式中,所以它应该为null,某些列名也应该重命名。 像ecpm
这样的一些专栏应该被删除。
将index
columns
添加到两个dataframes
并根据index
join
它们,这样就会有一对一的映射。 之后,只从joined
dataframe
select
所需的columns
。
如果您有两个dataframes
如下所示
// df1.show +-----+---+ | name|age| +-----+---+ |Alice| 25| | Bob| 29| | Tom| 26| +-----+---+ //df2.show +--------+-------+ | city|country| +--------+-------+ | Delhi| India| |New York| USA| | London| UK| +--------+-------+
现在添加index
columns
并获得一对一映射
import org.apache.spark.sql.functions._ val df1Index=df1.withColumn("index1",monotonicallyIncreasingId) val df2Index=df2.withColumn("index2",monotonicallyIncreasingId) val joinedDf=df1Index.join(df2Index,df1Index("index1")===df2Index("index2")) //joinedDf +-----+---+------+--------+-------+------+ | name|age|index1| city|country|index2| +-----+---+------+--------+-------+------+ |Alice| 25| 0| Delhi| India| 0| | Bob| 29| 1|New York| USA| 1| | Tom| 26| 2| London| UK| 2| +-----+---+------+--------+-------+------+
现在你可以写下如下查询
val queryList=List(col("name"),col("age"),col("country"))
joinedDf.select(queryList:_*).show
//Output df
+-----+---+-------+
| name|age|country|
+-----+---+-------+
|Alice| 25| India|
| Bob| 29| USA|
| Tom| 26| UK|
+-----+---+-------+
不确定是否有全自动的方法来实现这一目标。 如果你的模式是固定的,不是特别复杂,你可以手动调整模式和union
的结果。
为了讨论的方便,让我们说你要包含列col1
和col2
从frame1
和包括col2
和col4
的frame2
。
import org.apache.spark.sql.functions._
val subset1 = frame1.select($"col1", $"col2", lit(null).as("col4"))
val subset2 = frame2.select(lit(null).as("col1"), $"col2", $"col4")
val result = subset1 union subset2
实现这一目标。 我们手动指定每列,以便我们可以跳过任何我们喜欢的列。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.