Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 使用日期的空数据转换数据集_Scala_Apache Spark_Apache Spark Sql_Apache Spark Mllib - Fatal编程技术网

Scala 使用日期的空数据转换数据集

Scala 使用日期的空数据转换数据集,scala,apache-spark,apache-spark-sql,apache-spark-mllib,Scala,Apache Spark,Apache Spark Sql,Apache Spark Mllib,我有一个带有日期、accountid和值的数据集。我想将数据集转换为一个新的数据集,如果某个特定日期中不存在accountid,则针对该日期添加一个值为0的accountid。这可能吗 val df = sc.parallelize(Seq(("2018-01-01", 100.5,"id1"), ("2018-01-02", 120.6,"id1"), ("2018-01-03", 450.2,"id2") )).toDF("date", "val","accountid"

我有一个带有日期、accountid和值的数据集。我想将数据集转换为一个新的数据集,如果某个特定日期中不存在accountid,则针对该日期添加一个值为0的accountid。这可能吗

    val df = sc.parallelize(Seq(("2018-01-01", 100.5,"id1"),
  ("2018-01-02", 120.6,"id1"),
  ("2018-01-03", 450.2,"id2")
  )).toDF("date", "val","accountid")
    +----------+-----+---------+
|      date|  val|accountid|
+----------+-----+---------+
|2018-01-01|100.5|      id1|
|2018-01-02|120.6|      id1|
|2018-01-03|450.2|      id2|
+----------+-----+---------+
我想将此数据集转换为此格式

+----------+-----+---------+
|      date|  val|accountid|
+----------+-----+---------+
|2018-01-01|100.5|      id1|
|2018-01-01|  0.0|      id2|
|2018-01-02|120.6|      id1|
|2018-01-02|  0.0|      id2|
|2018-01-03|450.2|      id2|
|2018-01-03|0.0  |      id1|
+----------+-----+---------+

您可以创建引用

import org.apache.spark.sql.functions._
import org.apache.spark.sql.Row

val Row(minTs: Long, maxTs: Long) = df
  .select(to_date($"date").cast("timestamp").cast("bigint") as "date")
  .select(min($"date"), max($"date")).first

val by =  60 * 60 * 24

val ref = spark
  .range(minTs, maxTs + by, by)
  .select($"id".cast("timestamp").cast("date").cast("string").as("date"))
  .crossJoin(df.select("accountid").distinct)
与输入数据的外部联接:

ref.join(df, Seq("date", "accountid"), "leftouter").na.fill(0.0).show
// +----------+---------+-----+      
// |      date|accountid|  val|
// +----------+---------+-----+
// |2018-01-03|      id1|  0.0|
// |2018-01-01|      id1|100.5|
// |2018-01-02|      id2|  0.0|
// |2018-01-02|      id1|120.6|
// |2018-01-03|      id2|450.2|
// |2018-01-01|      id2|  0.0|
// +----------+---------+-----+
您可以简单地使用udf函数来满足您的需求

但在此之前,您必须获取完整的AccountID集,并将其广播以在udf函数中使用

udf函数返回的数组将被分解,最后选择列

当然,你需要一门案例课

应该给你什么

+----------+-----+---------+
|date      |val  |accountid|
+----------+-----+---------+
|2018-01-01|100.5|id1      |
|2018-01-01|0.0  |id2      |
|2018-01-02|120.6|id1      |
|2018-01-02|0.0  |id2      |
|2018-01-03|450.2|id2      |
|2018-01-03|0.0  |id1      |
+----------+-----+---------+

注意:在case类中使用value关键字,因为保留的标识符名称不能用作变量名称

太好了!它起作用了。有一个问题是,交叉连接函数是否需要大量的性能,比如说原始数据集是否包含1M记录?由于洗牌和从稀疏到密集的转换,整个过程的成本很高,但您无法真正避免成本和期望的结果。
case class accounts(date:String, value:Double, accountid:String)
+----------+-----+---------+
|date      |val  |accountid|
+----------+-----+---------+
|2018-01-01|100.5|id1      |
|2018-01-01|0.0  |id2      |
|2018-01-02|120.6|id1      |
|2018-01-02|0.0  |id2      |
|2018-01-03|450.2|id2      |
|2018-01-03|0.0  |id1      |
+----------+-----+---------+