为啥在使用动态变量名时在 Sparklyr 中加 1 实际上加 2?
Posted
技术标签:
【中文标题】为啥在使用动态变量名时在 Sparklyr 中加 1 实际上加 2?【英文标题】:Why does adding by 1 actually add by 2 in Sparklyr when using dynamic variable names?为什么在使用动态变量名时在 Sparklyr 中加 1 实际上加 2? 【发布时间】:2021-05-15 15:57:04 【问题描述】:当我运行以下代码时,我希望 Sepal_Width_2 列的值是 Sepal_Width + 1,但实际上是 Sepal_Width + 2。什么给出?
require(dplyr)
require(sparklyr)
Sys.setenv(SPARK_HOME='/usr/lib/spark')
sc <- spark_connect(master="yarn")
# for this example these variables are hard coded
# but in my actual code these are named dynamically
sw_name <- as.name('Sepal_Width')
sw2 <- "Sepal_Width_2"
sw2_name <- as.name(sw2)
ir <- copy_to(sc, iris)
print(head(ir %>% mutate(!!sw2 := sw_name))) # so far so good
# Source: spark<?> [?? x 6]
# Sepal_Length Sepal_Width Petal_Length Petal_Width Species Sepal_Width_2
# <dbl> <dbl> <dbl> <dbl> <chr> <dbl>
# 5.1 3.5 1.4 0.2 setosa 3.5
# 4.9 3 1.4 0.2 setosa 3
# 4.7 3.2 1.3 0.2 setosa 3.2
# 4.6 3.1 1.5 0.2 setosa 3.1
# 5 3.6 1.4 0.2 setosa 3.6
# 5.4 3.9 1.7 0.4 setosa 3.9
print(head(ir %>% mutate(!!sw2 := sw_name) %>% mutate(!!sw2 := sw2_name + 1))) # i guess 2+2 != 4?
# Source: spark<?> [?? x 6]
# Sepal_Length Sepal_Width Petal_Length Petal_Width Species Sepal_Width_2
# <dbl> <dbl> <dbl> <dbl> <chr> <dbl>
# 5.1 3.5 1.4 0.2 setosa 5.5
# 4.9 3 1.4 0.2 setosa 5
# 4.7 3.2 1.3 0.2 setosa 5.2
# 4.6 3.1 1.5 0.2 setosa 5.1
# 5 3.6 1.4 0.2 setosa 5.6
# 5.4 3.9 1.7 0.4 setosa 5.9
我的用例要求我使用您在上面看到的动态变量命名。在此示例中,它相当愚蠢(与直接使用变量相比),但在我的用例中,我在数百个不同的 spark 表中运行相同的函数。它们在列数和每列是什么(某些机器学习模型的输出)方面都具有相同的“模式”,但名称不同,因为每个表都包含不同模型的输出。这些名称是可预测的,但由于它们各不相同,因此我按照您在此处看到的动态构建它们,而不是硬编码它们。
当名称被硬编码时,Spark 似乎知道如何将 2 和 2 相加,但是当名称是动态的时,它会突然崩溃。
【问题讨论】:
加0.5允许加1,但是这种行为很奇怪... 【参考方案1】:您可能误用 as.name
导致 sparklyr
误解您的输入。
请注意,仅在本地表上工作时您的代码错误:
sw_name <- as.name('Sepal.Width') # swap "_" to "." to match variable names
sw2 <- "Sepal_Width_2"
sw2_name <- as.name(sw2)
data(iris)
print(head(iris %>% mutate(!!sw2 := sw_name)))
# Error: Problem with `mutate()` input `Sepal_Width_2`.
# x object 'Sepal.Width' not found
# i Input `Sepal_Width_2` is `sw_name`.
请注意,您同时使用了来自 rlang 的 !!
运算符和来自基本 R 的 as.name
。但您没有将它们一起使用,如 this 问题所示。
我建议您使用 rlang 包中的 sym
和 !!
而不是 as.name
,并且将两者都应用于作为列名的字符串。以下在本地工作,与non-standard evaluation guidance 一致。所以它应该转化为火花:
library(dplyr)
data(iris)
sw <- 'Sepal.Width'
sw2 <- paste0(sw, "_2")
head(iris %>% mutate(!!sym(sw2) := !!sym(sw)))
head(iris %>% mutate(!!sym(sw2) := !!sym(sw)) %>% mutate(!!sym(sw2) := !!sym(sw2) + 1))
【讨论】:
感谢您的建议。语法在 Sparklyr 中是合法且“有效”的,因为它可以运行,但是奇怪的行为仍然存在。我将尝试 sym 和 !! 的不同组合看看会发生什么。感谢您链接非标准评估指南。很清楚,但我会努力克服它。【参考方案2】:我不确定哪个包是罪魁祸首(sparklyr、dplyr、R,谁知道),但是当我从 3.6.3/sparklyr 1.5 升级到 R 4.0.2/sparklyr 1.7.0 时,这个问题已经得到解决。
【讨论】:
以上是关于为啥在使用动态变量名时在 Sparklyr 中加 1 实际上加 2?的主要内容,如果未能解决你的问题,请参考以下文章
获取 PSQLException:错误:在带有 Postgres 的 spark jdbc 中使用查询而不是表名时在“SELECT”处或附近出现语法错误
为啥 R lubridate::duration 数据类型使用 sparklyr 转换为 spark 中的字符?
在 R 和 Sparklyr 中,将表写入 .CSV (spark_write_csv) 会产生许多文件,而不是一个文件。为啥?我可以改变吗?