Почему я не могу использовать оператор двойного двоеточия с dplyr, если набор данных находится в sparklyr? - PullRequest
0 голосов
/ 24 октября 2018

Воспроизводимый пример (адаптированный из ответа @ 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

Ошибка:

 Error in dplyr::if_else(PaymentHistory < 0, 0, dplyr::if_else(PaymentHistory >  : 
 object 'PaymentHistory' not found 

Я использую оператор области действия, потому что боюсь, чтоимя в 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

1 Ответ

0 голосов
/ 25 октября 2018

TL; DR Поскольку ваш код вообще не использует dplyr::if_else.

sparklyr, при использовании в качестве примера рассматривает Spark как еще одну базу данных и выдает проблемызапросы, использующие dbplyr уровень перевода SQL .

В этом контексте 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

Однако, если вы передадите полностью определенное имя, он обойдет этот механизм, попытается оценить функцию и в конечном итоге потерпит неудачу, поскольку столбцы базы данных не находятся в области действия.

Ябоится, что имя в dplyr будет конфликтовать с некоторым из определенного пользователем кода.

Как видите, dplyr вообще не нужен, чтобы быть здесь в области видимости - функции, вызываемые в sparklyrконвейеры либо переводятся в соответствующие конструкции SQL, либо, если нет определенного правила преобразования, передаются как есть и разрешаются механизмом SQL Spark (этот путь используется для вызова функций 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))
Error in dplyr::if_else(mpg < 20, 1, 0) : object 'mpg' not found
...