Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/15.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
Apache spark 如何使用UDF返回多个列?_Apache Spark_Apache Spark Sql - Fatal编程技术网

Apache spark 如何使用UDF返回多个列?

Apache spark 如何使用UDF返回多个列?,apache-spark,apache-spark-sql,Apache Spark,Apache Spark Sql,是否可以创建一个将返回列集的UDF 即,具有如下数据帧: | Feature1 | Feature2 | Feature 3 | | 1.3 | 3.4 | 4.5 | | Feature1 | Feature2 | Feature 3 | Slope | Offset | | 1.3 | 3.4 | 4.5 | 0.5 | 3 | 现在我想提取一个新的特征,它可以被描述为两个元素的向量(例如,在线性回归中看到的斜

是否可以创建一个将返回列集的UDF

即,具有如下数据帧:

| Feature1 | Feature2 | Feature 3 |
| 1.3      | 3.4      | 4.5       |
| Feature1 | Feature2 | Feature 3 | Slope | Offset |
| 1.3      | 3.4      | 4.5       | 0.5   | 3      |
现在我想提取一个新的特征,它可以被描述为两个元素的向量(例如,在线性回归中看到的斜率和偏移量)。所需数据集应如下所示:

| Feature1 | Feature2 | Feature 3 |
| 1.3      | 3.4      | 4.5       |
| Feature1 | Feature2 | Feature 3 | Slope | Offset |
| 1.3      | 3.4      | 4.5       | 0.5   | 3      |

是否可以使用单个自定义项创建多个列,或者我是否需要遵循“每个自定义项一列”的规则?

Struct method

您可以将
udf
函数定义为

def myFunc: (String => (String, String)) = { s => (s.toLowerCase, s.toUpperCase)}

import org.apache.spark.sql.functions.udf
val myUDF = udf(myFunc)
并使用
*
作为

val newDF = df.withColumn("newCol", myUDF(df("Feature2"))).select("Feature1", "Feature2", "Feature 3", "newCol.*")
我从
udf
函数返回了
Tuple2
,用于测试(根据需要多少多列,可以使用高阶元组),它将被视为
struct
列。然后,您可以使用
*
选择单独列中的所有元素,并最终重命名它们

您应该将输出设置为

+--------+--------+---------+---+---+
|Feature1|Feature2|Feature 3|_1 |_2 |
+--------+--------+---------+---+---+
|1.3     |3.4     |4.5      |3.4|3.4|
+--------+--------+---------+---+---+
您可以重命名
\u 1
\u 2

数组方法

udf
函数应返回一个
数组

def myFunc: (String => Array[String]) = { s => Array("s".toLowerCase, s.toUpperCase)}

import org.apache.spark.sql.functions.udf
val myUDF = udf(myFunc)
您可以选择
数组的元素
,并使用
别名
对其进行重命名

val newDF = df.withColumn("newCol", myUDF(df("Feature2"))).select($"Feature1", $"Feature2", $"Feature 3", $"newCol"(0).as("Slope"), $"newCol"(1).as("Offset"))
你应该

+--------+--------+---------+-----+------+
|Feature1|Feature2|Feature 3|Slope|Offset|
+--------+--------+---------+-----+------+
|1.3     |3.4     |4.5      |s    |3.4   |
+--------+--------+---------+-----+------+

此外,还可以返回case类:

case class NewFeatures(slope: Double, offset: Int)

val getNewFeatures = udf { s: String =>
      NewFeatures(???, ???)
    }

df
  .withColumn("newF", getNewFeatures($"Feature1"))
  .select($"Feature1", $"Feature2", $"Feature3", $"newF.slope", $"newF.offset")

这是一个很好的解决方案,谢谢!另一个问题是,UDF被称为多少次?我添加了计数器来计算调用次数,在上面的代码中,UDF被调用了3次。有没有办法解决这个问题?@RameshMaharjan我看到了你关于处理
df
中所有列的另一个答案,再加上这一点,它们提供了一个很好的解决方案。但是,我一直坚持使用
UDF
的返回值,使用
with column
修改多个列,每次只取一个列名。你知道解决办法吗?