расчет qchisq в таблице sparklyr

Мне нужно использовать функцию qchisq для столбца фрейма данных sparklyr.

Проблема в том, что кажется, что функция qchisq не реализована в Spark. Если я правильно читаю приведенное ниже сообщение об ошибке, sparklyr пытался выполнить функцию под названием «QCHISQ», однако ее нет ни в Hive SQL, ни в Spark.

В общем, есть ли способ запустить произвольные функции, не реализованные в Hive или Spark, с помощью sparklyr? Я знаю про spark_apply, но пока не разобрался, как его настроить.

> mydf = data.frame(beta=runif(100, -5, 5), pval = runif(100, 0.001, 0.1))
> mydf_tbl = copy_to(con, mydf)

> mydf_tbl
# Source:   table<mydf> [?? x 2]
# Database: spark_connection
     beta    pval
    <dbl>   <dbl>
 1  3.42  0.0913
 2 -1.72  0.0629
 3  0.515 0.0335
 4 -3.12  0.0717
 5 -2.12  0.0253
 6  1.36  0.00640
 7 -3.33  0.0896
 8  1.36  0.0235
 9  0.619 0.0414
10  4.73  0.0416

> mydf_tbl %>% mutate(se = sqrt(beta^2/qchisq(pval)))
Error: org.apache.spark.sql.AnalysisException: Undefined function: 'QCHISQ'. 
This function is neither a registered temporary function nor a permanent function registered in the database 'default'.; line 1 pos 49

person dalloliogm    schedule 16.05.2018    source источник


Ответы (2)


Как вы заметили, вы можете использовать spark_apply:

mydf_tbl %>% 
  spark_apply(function(df) 
    dplyr::mutate(df, se = sqrt(beta^2/qchisq(pval, df = 12))))

# # Source:   table<sparklyr_tmp_14bd5feacf5> [?? x 3]
# # Database: spark_connection
#      beta   pval     X3
#     <dbl>  <dbl>  <dbl>
#  1  1.66  0.0763 0.686 
#  2  0.153 0.0872 0.0623
#  3  2.96  0.0485 1.30  
#  4  4.86  0.0349 2.22  
#  5 -1.82  0.0712 0.760 
#  6  2.34  0.0295 1.10  
#  7  3.54  0.0297 1.65  
#  8  4.57  0.0784 1.88  
#  9  4.94  0.0394 2.23  
# 10 -0.610 0.0906 0.246 
# # ... with more rows

но справедливое предупреждение - это смущающе медленно. К сожалению, здесь у вас нет альтернативы, кроме написания собственных расширений Scala/Java.

person Alper t. Turker    schedule 16.05.2018
comment
Спасибо, в любом случае. Мне потребовалось много времени, чтобы понять, что альтернатив нет, так что хорошо, что вы можете это подтвердить. - person dalloliogm; 17.05.2018

В конце концов, я использовал ужасный хак, который отлично работает в этом случае.

Другим решением было бы написать определяемую пользователем функцию (UDF), но sparklyr пока не поддерживает ее: https://github.com/rstudio/sparklyr/issues/1052

Это хак, который я использовал. Короче говоря, я предварительно вычисляю таблицу qchisq, загружаю ее как объект sparklyr, а затем присоединяюсь. Если я сравню это с результатами, рассчитанными на локальном фрейме данных, я получу корреляцию r = 0,99999990902236146617.

#' @param n: number of significant digits to use
> check_precomputed_strategy = function(n) { 
    chisq = data.frame(pval=seq(0, 1, 1/(10**(n)))) %>%
            mutate(qval=qchisq(pval, df=1, lower.tail = FALSE)) %>%
            mutate(pval_s = as.character(round(as.integer(pval*10**n),0)))
    chisq %>% head %>% print
    chisq_tbl = copy_to(con, chisq, overwrite=T)

    mydf = data.frame(beta=runif(100, -5, 5), pval = runif(100, 0.001, 0.1)) %>%
        mutate(se1 = sqrt(beta^2/qchisq(pval, df=1, lower.tail = FALSE)))
    mydf_tbl = copy_to(con, mydf)

    mydf_tbl.up  = mydf_tbl %>%
            mutate(pval_s=as.character(round(as.integer(pval*10**n),0)))  %>%
            left_join(chisq_tbl, by="pval_s") %>%
            mutate(se=sqrt(beta^2 / qval)) %>%
            collect %>%
            filter(!duplicated(beta))

    mydf_tbl.up %>% head %>% print
    mydf_tbl.up %>% filter(complete.cases(.)) %>% nrow %>% print
    mydf_tbl.up %>% filter(complete.cases(.)) %>% select(se, se1) %>% cor

}
> check_precomputed_strategy(4)
                       pval                  qval pval_s
1 0.00000000000000000000000                   Inf      0
2 0.00010000000000000000479 15.136705226623396570      1
3 0.00020000000000000000958 13.831083619091122827      2
4 0.00030000000000000002793 13.070394140069462097      3
5 0.00040000000000000001917 12.532193305401813532      4
6 0.00050000000000000001041 12.115665146397173402      5
# A tibble: 6 x 8
    beta  pval.x   se1 myvar pval_s  pval.y  qval    se
   <dbl>   <dbl> <dbl> <dbl> <chr>    <dbl> <dbl> <dbl>
1  3.42  0.0913  2.03     1. 912    0.0912   2.85 2.03
2 -1.72  0.0629  0.927    1. 628    0.0628   3.46 0.927
3  0.515 0.0335  0.242    1. 335    0.0335   4.52 0.242
4 -3.12  0.0717  1.73     1. 716    0.0716   3.25 1.73
5 -2.12  0.0253  0.947    1. 253    0.0253   5.00 0.946
6  1.36  0.00640 0.498    1. 63     0.00630  7.46 0.497
[1] 100
                        se                    se1
se  1.00000000000000000000 0.99999990902236146617
se1 0.99999990902236146617 1.00000000000000000000
person dalloliogm    schedule 17.05.2018