在 SparklyR 中展开/在 Spark 中进行枢轴

Spread in SparklyR / pivot in Spark

我正在尝试将我的 R 代码(如下所示)重构为 Sparklyr R 代码以处理 spark 数据集以获得最终结果,如 Table 1:

所示

借助堆栈溢出的帮助 post and SparklyR separate one Spark Data Frame column into two columns 除了处理 Spread 的最后一步外,我能够一路走来。

需要帮助:

  1. 通过 SparklyR 实现 Spread
  2. 以任何方式优化代码

Table 1:需要最终输出:

  var              n nmiss
1 Sepal.Length   150     0
2 Sepal.Width    150     0

R代码实现:

library(dplyr)
library(tidyr)
library(tibble)

data <- iris
data_tbl <- as_tibble(data)

profile <- data_tbl %>%
  select(Sepal.Length,Sepal.Width) %>%
  summarize_all(funs(
    n = n(), #Count
    nmiss=sum(as.numeric(is.na(.))) # MissingCount
   )) %>%
  gather(variable, value) %>%
  separate(variable, c("var", "stat"), sep = "_(?=[^_]*$)") %>% 
  spread(stat, value) 

火花代码:

sdf_gather <- function(tbl){
  all_cols <- colnames(tbl)
  lapply(all_cols, function(col_nm){
    tbl %>% 
      select(col_nm) %>% 
      mutate(key = col_nm) %>%
      rename(value = col_nm)  
  }) %>% 
    sdf_bind_rows() %>% 
    select(c('key', 'value'))
}


profile <- data_tbl %>%
  select(Sepal.Length,Sepal.Width ) %>%
  summarize_all(funs(
    n = n(), 
    nmiss=sum(as.numeric(is.na(.))) 
  )) %>%
  sdf_gather(.) %>%
  ft_regex_tokenizer(input_col="key", output_col="KeySplit", pattern="_(?=[^_]*$)") %>% 
  sdf_separate_column("KeySplit", into=c("var", "stat")) %>%
  select(var,stat,value) %>%
  sdf_register('profile')

在这种特定情况下(通常所有列都具有相同类型,但如果您只对缺失数据统计感兴趣,则可以进一步放宽)您可以使用比这简单得多的结构。

数据定义如下:

df <- copy_to(sc, iris, overwrite = TRUE) 

gather 列(下面我假设一个函数定义在 to

long <- df %>% 
  select(Sepal_Length, Sepal_Width) %>% 
  sdf_gather("key", "value", "Sepal_Length", "Sepal_Width")

然后分组聚合:

long %>% 
  group_by(key) %>% 
  summarise(n = n(), nmiss = sum(as.numeric(is.na(value)), na.rm=TRUE))

结果为:

# Source: spark<?> [?? x 3]
  key              n nmiss
  <chr>        <dbl> <dbl>
1 Sepal_Length   150     0
2 Sepal_Width    150     0

鉴于输出的大小减小,在聚合后收集结果也很好

agg <- df %>%
  select(Sepal_Length,Sepal_Width) %>%
    summarize_all(funs(
      n = n(),
      nmiss=sum(as.numeric(is.na(.))) # MissingCount
   )) %>% collect()

并在结果上应用您的 gather - spread 逻辑:

agg %>% 
  tidyr::gather(variable, value) %>%
  tidyr::separate(variable, c("var", "stat"), sep = "_(?=[^_]*$)") %>% 
  tidyr::spread(stat, value) 
# A tibble: 2 x 3
  var              n nmiss
  <chr>        <dbl> <dbl>
1 Sepal_Length   150     0
2 Sepal_Width    150     0

事实上,在这种特殊情况下,后一种方法在性能方面应该更胜一筹。