【发布时间】:2018-04-25 01:38:58
【问题描述】:
让我用一个例子来解释我想要实现的目标。 以 DataFrame 开头,如下所示:
val df = Seq((1, "CS", 0, (0.1, 0.2, 0.4, 0.5)),
(4, "Ed", 0, (0.4, 0.8, 0.3, 0.6)),
(7, "CS", 0, (0.2, 0.5, 0.4, 0.7)),
(101, "CS", 1, (0.5, 0.7, 0.3, 0.8)),
(5, "CS", 1, (0.4, 0.2, 0.6, 0.9)))
.toDF("id", "dept", "test", "array")
+---+----+----+--------------------+
| id|dept|test| array|
+---+----+----+--------------------+
| 1| CS| 0|[0.1, 0.2, 0.4, 0.5]|
| 4| Ed| 0|[0.4, 0.8, 0.3, 0.6]|
| 7| CS| 0|[0.2, 0.5, 0.4, 0.7]|
|101| CS| 1|[0.5, 0.7, 0.3, 0.8]|
| 5| CS| 1|[0.4, 0.2, 0.6, 0.9]|
+---+----+----+--------------------+
我想根据id、dept和test列的信息来改变数组列的一些元素。我首先将索引添加到不同部门的每一行,如下所示:
@transient val w = Window.partitionBy("dept").orderBy("id")
val tempdf = df.withColumn("Index", row_number().over(w))
tempdf.show
+---+----+----+--------------------+-----+
| id|dept|test| array|Index|
+---+----+----+--------------------+-----+
| 1| CS| 0|[0.1, 0.2, 0.4, 0.5]| 1|
| 5| CS| 1|[0.4, 0.2, 0.6, 0.9]| 2|
| 7| CS| 0|[0.2, 0.5, 0.4, 0.7]| 3|
|101| CS| 1|[0.5, 0.7, 0.3, 0.8]| 4|
| 4| Ed| 0|[0.4, 0.8, 0.3, 0.6]| 1|
+---+----+----+--------------------+-----+
我想要实现的是从数组列中的一个元素中减去一个常量(0.1),它的位置对应于每个部门内行的索引。例如,在“dept==CS”的情况下,最终结果应该是:
+---+----+----+--------------------+-----+
| id|dept|test| array|Index|
+---+----+----+--------------------+-----+
| 1| CS| 0|[0.0, 0.2, 0.4, 0.5]| 1|
| 5| CS| 1|[0.4, 0.1, 0.6, 0.9]| 2|
| 7| CS| 0|[0.2, 0.5, 0.3, 0.7]| 3|
|101| CS| 1|[0.5, 0.7, 0.3, 0.7]| 4|
| 4| Ed| 0|[0.4, 0.8, 0.3, 0.6]| 1|
+---+----+----+--------------------+-----+
目前,我正在考虑使用 udf 实现这一点,如下所示:
def subUdf = udf((array: Seq[Double], dampFactor: Double, additionalIndex: Int) => additionalIndex match{
case 0 => array
case _ => { val temp = array.zipWithIndex
var mask = Array.fill(array.length)(0.0)
mask(additionalIndex-1) = dampFactor
val tempAdj = temp.map(x => if (additionalIndex == (x._2+1)) (x._1-mask, x._2) else x)
tempAdj.map(_._1)
}
}
)
val dampFactor = 0.1
val finaldf = tempdf.withColumn("array", subUdf(tempdf("array"), dampFactor, when(tempdf("dept") === "CS" && tempdf("test") === 0, tempdf("Index")).otherwise(lit(0)))).drop("Index")
由于重载方法导致udf编译错误:
Name: Compile Error
Message: <console>:34: error: overloaded method value - with alternatives:
(x: Double)Double <and>
(x: Float)Double <and>
(x: Long)Double <and>
(x: Int)Double <and>
(x: Char)Double <and>
(x: Short)Double <and>
(x: Byte)Double
cannot be applied to (Array[Double])
val tempAdj = temp.map(x => if (additionalIndex == (x._2+1)) (x._1-mask, x._2) else x)
^
两个相关问题:
如何解决编译错误?
我也愿意建议使用 udf 以外的方法来实现这一目标。
【问题讨论】:
标签: scala apache-spark