Java 数据帧透视-Spark SQL
我有一个包含以下内容的数据框:Java 数据帧透视-Spark SQL,java,scala,apache-spark,apache-spark-sql,pivot,Java,Scala,Apache Spark,Apache Spark Sql,Pivot,我有一个包含以下内容的数据框: TradeId |来源 ABC |“333.12320170605美元,-789.44420170605英镑1234.56720150602” 我想将这些数据转换为以下内容 TradeId | CCY | PV ABC |美元| 333.123 ABC |美元|-789.444 美国银行1234.567英镑 “源”列中CCY | PV |日期三元组的数量不是固定的。我可以在ArrayList中完成,但这需要在JVM中加载数据,这就破坏了Spark的全部功能 假
TradeId |来源
ABC |“333.12320170605美元,-789.44420170605英镑1234.56720150602”
我想将这些数据转换为以下内容
TradeId | CCY | PV
ABC |美元| 333.123
ABC |美元|-789.444
美国银行1234.567英镑
“源”列中CCY | PV |日期三元组的数量不是固定的。我可以在ArrayList中完成,但这需要在JVM中加载数据,这就破坏了Spark的全部功能
假设我的数据框如下所示:
DataFrame tradesSnap = this.loadTradesSnap(reportRequest);
String tempTable = getTempTableName();
tradesSnap.registerTempTable(tempTable);
tradesSnap = tradesSnap.sqlContext().sql("SELECT TradeId, Source FROM " + tempTable);
您试图实现的目标看起来更像是
flatMap
,而不是旋转
简单地说,通过在数据集上使用flatMap
,可以将一个函数(map
)应用于每一行,该函数本身将生成一系列行。然后将每组行连接成单个序列(flat
)
以下程序显示了这一想法:
import org.apache.spark.sql.SparkSession
case class Input(TradeId: String, Source: String)
case class Output(TradeId: String, CCY: String, PV: String, Date: String)
object FlatMapExample {
// This function will produce more rows of output for each line of input
def splitSource(in: Input): Seq[Output] =
in.Source.split("\\|", -1).map {
source =>
println(source)
val Array(ccy, pv, date) = source.split(",", -1)
Output(in.TradeId, ccy, pv, date)
}
def main(args: Array[String]): Unit = {
// Initialization and loading
val spark = SparkSession.builder().master("local").appName("pivoting-example").getOrCreate()
import spark.implicits._
val input = spark.read.options(Map("sep" -> "|", "header" -> "true")).csv(args(0)).as[Input]
// For each line in the input, split the source and then
// concatenate each "sub-sequence" in a single `Dataset`
input.flatMap(splitSource).show
}
}
根据您的输入,这将是输出:
+-------+---+--------+--------+
|TradeId|CCY| PV| Date|
+-------+---+--------+--------+
| ABC|USD| 333.123|20170605|
| ABC|USD|-789.444|20170605|
| ABC|GBP|1234.567|20150602|
+-------+---+--------+--------+
如果需要,您现在可以获取结果并将其保存到CSV中。您尝试实现的目标看起来更像是平面地图,而不是旋转
简单地说,通过在数据集上使用flatMap
,可以将一个函数(map
)应用于每一行,该函数本身将生成一系列行。然后将每组行连接成单个序列(flat
)
以下程序显示了这一想法:
import org.apache.spark.sql.SparkSession
case class Input(TradeId: String, Source: String)
case class Output(TradeId: String, CCY: String, PV: String, Date: String)
object FlatMapExample {
// This function will produce more rows of output for each line of input
def splitSource(in: Input): Seq[Output] =
in.Source.split("\\|", -1).map {
source =>
println(source)
val Array(ccy, pv, date) = source.split(",", -1)
Output(in.TradeId, ccy, pv, date)
}
def main(args: Array[String]): Unit = {
// Initialization and loading
val spark = SparkSession.builder().master("local").appName("pivoting-example").getOrCreate()
import spark.implicits._
val input = spark.read.options(Map("sep" -> "|", "header" -> "true")).csv(args(0)).as[Input]
// For each line in the input, split the source and then
// concatenate each "sub-sequence" in a single `Dataset`
input.flatMap(splitSource).show
}
}
根据您的输入,这将是输出:
+-------+---+--------+--------+
|TradeId|CCY| PV| Date|
+-------+---+--------+--------+
| ABC|USD| 333.123|20170605|
| ABC|USD|-789.444|20170605|
| ABC|GBP|1234.567|20150602|
+-------+---+--------+--------+
如果您愿意,您现在可以获取结果并将其保存到CSV中。如果您阅读,它会说“pivot是一个聚合,其中一个(或多个在一般情况下)分组列的不同值被转换到各个列中。”
我想这不是您想要的
我建议您使用并获得所需的最终输出。考虑到您拥有的是dataframe
,您可以执行以下操作
+-------+----------------------------------------------------------------+
|TradeId|Source |
+-------+----------------------------------------------------------------+
|ABC |USD,333.123,20170605|USD,-789.444,20170605|GBP,1234.567,20150602|
+-------+----------------------------------------------------------------+
您可以使用explode
、split
和withColumn
执行以下操作,以获得所需的输出
val explodedDF = dataframe.withColumn("Source", explode(split(col("Source"), "\\|")))
val finalDF = explodedDF.withColumn("CCY", split($"Source", ",")(0))
.withColumn("PV", split($"Source", ",")(1))
.withColumn("Date", split($"Source", ",")(2))
.drop("Source")
finalDF.show(false)
最终输出为
+-------+---+--------+--------+
|TradeId|CCY|PV |Date |
+-------+---+--------+--------+
|ABC |USD|333.123 |20170605|
|ABC |USD|-789.444|20170605|
|ABC |GBP|1234.567|20150602|
+-------+---+--------+--------+
我希望这能解决您的问题如果您阅读,它会说,“pivot是一个聚合,其中一个(在一般情况下是多个)分组列的不同值被转换为单独的列。”
我想这不是您想要的
我建议您使用并获得所需的最终输出。考虑到您拥有的是dataframe
,您可以执行以下操作
+-------+----------------------------------------------------------------+
|TradeId|Source |
+-------+----------------------------------------------------------------+
|ABC |USD,333.123,20170605|USD,-789.444,20170605|GBP,1234.567,20150602|
+-------+----------------------------------------------------------------+
您可以使用explode
、split
和withColumn
执行以下操作,以获得所需的输出
val explodedDF = dataframe.withColumn("Source", explode(split(col("Source"), "\\|")))
val finalDF = explodedDF.withColumn("CCY", split($"Source", ",")(0))
.withColumn("PV", split($"Source", ",")(1))
.withColumn("Date", split($"Source", ",")(2))
.drop("Source")
finalDF.show(false)
最终输出为
+-------+---+--------+--------+
|TradeId|CCY|PV |Date |
+-------+---+--------+--------+
|ABC |USD|333.123 |20170605|
|ABC |USD|-789.444|20170605|
|ABC |GBP|1234.567|20150602|
+-------+---+--------+--------+
我希望这能解决你的问题是的,我最终也找到了这个选择。它更容易理解,甚至可以将它添加到我最初的select查询中。很高兴听到@Archilles。谢谢你的接受和支持:)是的,我最终也找到了这个选择。它更容易理解,甚至可以将它添加到我最初的select查询中。很高兴听到@Archilles。感谢您的接受和投票:)