使用 Spark 将函数中的多个列名传递给 dplyr::distinct()

Posted

技术标签:

【中文标题】使用 Spark 将函数中的多个列名传递给 dplyr::distinct()【英文标题】:Pass multiple column names in function to dplyr::distinct() with Spark 【发布时间】:2021-08-16 00:04:57 【问题描述】:

我想在将使用dplyr::distinct() 的函数中指定未知数量的列名。我目前的尝试是:

myFunction <- function(table, id) 
  table %>%
    dplyr::distinct(.data[[id]])

我正在尝试上述 [.data[[id]]] 因为the data-masking section of this dplyr blog 状态:

当您有一个字符向量的 env 变量时,您需要使用 [[ 来索引 .data 代词,例如 summarise(df, mean = mean(.data[[var]]))。

dplyr::distinct() 的文档说明了它的第二个参数:

&lt;data-masking&gt; 确定唯一性时使用的可选变量。如果给定的输入组合有多行,则仅保留第一行。如果省略,将使用所有变量。

火花

更具体地说,我正在尝试将此功能与 Spark 一起使用。

sc <- sparklyr::spark_connect(local = "master")
mtcars_tbl <- sparklyr::copy_to(sc, mtcars, "mtcars_spark")

##### desired return
mtcars_tbl %>% dplyr::distinct(cyl, gear)
# Source: spark<?> [?? x 2]
    cyl  gear
  <dbl> <dbl>
1     6     4
2     4     4
3     6     3
4     8     3
5     4     3
6     4     5
7     8     5
8     6     5

##### myFunction fails
id = c("cyl", "gear")
myFunction(mtcars_tbl, id)
 Error: Can't convert a call to a string
Run `rlang::last_error()` to see where the error occurred. 

在this comment之后,我还有其他失败的尝试:

myFunction <- function(table, id) 
    table %>%
        dplyr::distinct(.dots = id)


myFunction(mtcars_tbl, id)
# Source: spark<?> [?? x 1]
  .dots           
  <list>          
1 <named list [2]>


#####


myFunction <- function(table, id) 
    table %>%
        dplyr::distinct_(id)


myFunction(mtcars_tbl, id)
Error in UseMethod("distinct_") : 
  no applicable method for 'distinct_' applied to an object of class "c('tbl_spark', 'tbl_sql', 'tbl_lazy', 'tbl')"

【问题讨论】:

【参考方案1】:

Distinct 一次适用于表的所有列。考虑一个示例表:

A     B
1     4
1     4
2     3
2     3
3     3
3     5

目前尚不清楚仅对 A 列应用 distinct 而不是 B 列应返回什么。下面的例子显然不是一个好的选择,因为它破坏了 A 列和 B 列之间的关系。例如,原始数据集中没有 (A = 2, B = 4) 行。

A     B
1     4
2     4
3     3
      3
      3
      5

因此,最好的方法是先只选择您想要的那些列,然后再选择不同的列。更像是:

myFunction <- function(table, id) 
  table %>%
    dplyr::select(dplyr::all_of(id)) %>%
    dplyr::distinct()

【讨论】:

分两步的绝妙招式!但是请注意,当id = c("cyl", "gear")(或以其他方式保存多个数据变量名称)时,错误为Error: Must subset the data pronoun with a string。因此,我认为您无法使用当前代码(至少使用 dplyr 1.0.6)达到我的“期望回报”。如果您将您的选择语句更改为dplyr::select(dplyr::all_of(id)),我将很乐意接受。谢谢。 当然可以。感谢您的更正,我没有仔细测试我的答案的那部分。我使用的另一种方法是select(!!!syms(id))。这会将字符串转换为符号,但在此应用程序中不如 all_of 清晰。

以上是关于使用 Spark 将函数中的多个列名传递给 dplyr::distinct()的主要内容,如果未能解决你的问题,请参考以下文章

如何将 dplyr 中的动态列名传递给自定义函数?

如何将数组传递给 Spark (UDAF) 中的用户定义聚合函数

将 data.frame 列名传递给函数

如何遍历表的列名并将值传递给 MSSQL while 循环中的 UDF

怎样给Spark传递函数

如何在sql server中的标量函数中传递列名[关闭]