使用 x.head、x.tail 的原因:_* 在 Spark 中
Reason behind using x.head, x.tail: _* in Spark
我想更改数据框中列的顺序,发现正确的方法如下:
val reorderedColumnNames: Array[String] = ??? // the new order of columns
val result: DataFrame = dataFrame.select(reorderedColumnNames.head, reorderedColumnNames.tail: _*)
我的问题是:
如果冒号“:_*”应该为您提供集合(Seq、List 或 Array)的所有元素,为什么不能像下面这样完成?
val result: DataFrame = dataFrame.select(reorderedColumnNames: _*)
我不明白为什么第二种方式不被 Spark 接受(并产生错误),因为这两种方式应该是等价的
Dataset
的API需要这样。
首先,Dataframe
(我记得从 2.0 开始,或多或少)只是实现方面的 Dataset[Row]
,因此您必须检查 API doc of Dataset。
查看 select
方法,有两种实现可供选择。
def select(col: String, cols: String*): DataFrame
这个接受单个 String
,后跟任意数量的 String
。
def select(cols: Column*): DataFrame
这个接受任意数量的 Column
个实例。
您的示例代码:val reorderedColumnNames: Array[String]
是一个字符串数组。因此,您只能使用该方法的字符串变体,这需要使用至少一个 String
参数,后面可能还有其他参数。
这就是为什么你不能直接扩展你的数组。
如果您要将 Array[String]
转换为 Array[Column]
,它会起作用,即:
val reorderedColumnNamesAsCols: Array[Column] = reorderedColumnNames.map(col(_))
dataFrame.select(reorderedColumnNamesAsCols: _*)
现在为什么不也提出一个 select(cols: String*)
变体呢?我不知道是否/为什么有人提出这个建议,但我 猜测 它不会被编译器很好地播放。
我们可以检查:
scala> class Test {
| def test(strs: String*): Unit = {}
| def test(nbrs: Integer*): Unit = {}
| }
<console>:13: error: double definition:
def test(strs: String*): Unit at line 12 and
def test(nbrs: Integer*): Unit at line 13
have same type after erasure: (strs: Seq)Unit
def test(nbrs: Integer*): Unit = {}
^
编译器不高兴。
我想更改数据框中列的顺序,发现正确的方法如下:
val reorderedColumnNames: Array[String] = ??? // the new order of columns
val result: DataFrame = dataFrame.select(reorderedColumnNames.head, reorderedColumnNames.tail: _*)
我的问题是:
如果冒号“:_*”应该为您提供集合(Seq、List 或 Array)的所有元素,为什么不能像下面这样完成?
val result: DataFrame = dataFrame.select(reorderedColumnNames: _*)
我不明白为什么第二种方式不被 Spark 接受(并产生错误),因为这两种方式应该是等价的
Dataset
的API需要这样。
首先,Dataframe
(我记得从 2.0 开始,或多或少)只是实现方面的 Dataset[Row]
,因此您必须检查 API doc of Dataset。
查看 select
方法,有两种实现可供选择。
def select(col: String, cols: String*): DataFrame
这个接受单个 String
,后跟任意数量的 String
。
def select(cols: Column*): DataFrame
这个接受任意数量的 Column
个实例。
您的示例代码:val reorderedColumnNames: Array[String]
是一个字符串数组。因此,您只能使用该方法的字符串变体,这需要使用至少一个 String
参数,后面可能还有其他参数。
这就是为什么你不能直接扩展你的数组。
如果您要将 Array[String]
转换为 Array[Column]
,它会起作用,即:
val reorderedColumnNamesAsCols: Array[Column] = reorderedColumnNames.map(col(_))
dataFrame.select(reorderedColumnNamesAsCols: _*)
现在为什么不也提出一个 select(cols: String*)
变体呢?我不知道是否/为什么有人提出这个建议,但我 猜测 它不会被编译器很好地播放。
我们可以检查:
scala> class Test {
| def test(strs: String*): Unit = {}
| def test(nbrs: Integer*): Unit = {}
| }
<console>:13: error: double definition:
def test(strs: String*): Unit at line 12 and
def test(nbrs: Integer*): Unit at line 13
have same type after erasure: (strs: Seq)Unit
def test(nbrs: Integer*): Unit = {}
^
编译器不高兴。