Cat*_*331 2 r dplyr apache-spark sparklyr
一个可重现的例子(改编自@forestfanjoe 的回答):
library(dplyr)
library(sparklyr)
sc <- spark_connect(master = "local")
df <- data.frame(id = 1:100, PaymentHistory = runif(n = 100, min = -1, max = 2))
df <- copy_to(sc, df, "payment")
> head(df)
# Source: spark<?> [?? x 2]
id PaymentHistory
* <int> <dbl>
1 1 -0.138
2 2 -0.249
3 3 -0.805
4 4 1.30
5 5 1.54
6 6 0.936
fix_PaymentHistory <- function(df){df %>% dplyr::mutate(PaymentHistory = dplyr::if_else(PaymentHistory < 0, 0, dplyr::if_else(PaymentHistory > 1,1, PaymentHistory)))}
df %>% fix_PaymentHistory
Run Code Online (Sandbox Code Playgroud)
错误是:
Error in dplyr::if_else(PaymentHistory < 0, 0, dplyr::if_else(PaymentHistory > :
object 'PaymentHistory' not found
Run Code Online (Sandbox Code Playgroud)
我正在使用范围运算符,因为我担心中的名称dplyr会与某些用户定义的代码发生冲突。请注意,PaymentHistory是 中的列变量df。
运行以下代码时不会出现相同的错误:
fix_PaymentHistory <- function(df){
df %>% mutate(PaymentHistory = if_else(PaymentHistory < 0, 0,if_else(PaymentHistory > 1,1, PaymentHistory)))
}
> df %>% fix_PaymentHistory
# Source: spark<?> [?? x 2]
id PaymentHistory
* <int> <dbl>
1 1 0
2 2 0
3 3 0
4 4 1
5 5 1
6 6 0.936
7 7 0
8 8 0.716
9 9 0
10 10 0.0831
# ... with more rows
Run Code Online (Sandbox Code Playgroud)
TL;DR因为您的代码根本不使用dplyr::if_else。
sparklyr,在示例中使用时,将 Spark 视为另一个数据库,并使用dbplyrSQL 转换层发出查询。
在此上下文if_else中不被视为函数,而是被转换为 SQL 原语的标识符:
dbplyr::translate_sql(if_else(PaymentHistory < 0, 0,if_else(PaymentHistory > 1,1, PaymentHistory)))
# <SQL> CASE WHEN ("PaymentHistory" < 0.0) THEN (0.0) WHEN NOT("PaymentHistory" < 0.0) THEN (CASE WHEN ("PaymentHistory" > 1.0) THEN (1.0) WHEN NOT("PaymentHistory" > 1.0) THEN ("PaymentHistory") END) END
Run Code Online (Sandbox Code Playgroud)
但是如果传递一个完全限定的named,就会绕过这个机制,尝试对函数求值,最终失败,因为数据库列不在范围内。
恐怕dplyr 中的名称会与某些用户定义的代码发生冲突。
如您所见,这里根本不需要 dplyr 的作用域——sparklyr管道中调用的函数要么被转换为相应的 SQL 构造,要么如果没有特定的转换规则,则按原样传递并由 Spark SQL 解析引擎(此路径用于调用Spark 函数)。
当然,此机制并非特定于sparklyr,您可能会看到使用由数据库支持的其他表的相同行为:
library(magrittr)
db <- dplyr::src_sqlite(":memory:", TRUE)
dplyr::copy_to(db, mtcars)
db %>% dplyr::tbl("mtcars") %>% dplyr::mutate(dplyr::if_else(mpg < 20, 1, 0))
Run Code Online (Sandbox Code Playgroud)
dbplyr::translate_sql(if_else(PaymentHistory < 0, 0,if_else(PaymentHistory > 1,1, PaymentHistory)))
# <SQL> CASE WHEN ("PaymentHistory" < 0.0) THEN (0.0) WHEN NOT("PaymentHistory" < 0.0) THEN (CASE WHEN ("PaymentHistory" > 1.0) THEN (1.0) WHEN NOT("PaymentHistory" > 1.0) THEN ("PaymentHistory") END) END
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
330 次 |
| 最近记录: |