Репликация решения plyr, генерирующего квантили с Hmisc в dplyr - PullRequest
0 голосов
/ 01 мая 2019

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

Вот пример 'plyr':

# load packages
if(!require("pacman"))install.packages("pacman")
p_load(dplyr, plyr, Hmisc, tidyverse)

    # generate data
    df_samp <- tibble(
    x_var  = rnorm(100, 0, 1),
    levels = rep(c('a', 'b', 'c', 'd'), 25))

    # working plyr solution that groups data by level and calculates quantiles within levels
    plyr_solution <- plyr::ddply(df_samp,~ levels,
                                 summarise, X = wtd.Ecdf(x_var)$x, 
                                 Y = wtd.Ecdf(x_var)$ecdf)
    plyr_solution

    # dplyr attempt

    dplyr_solution <- df_samp %>% 
    dplyr::select(levels, x_var) %>%
    dplyr::group_by(levels) %>%
    dplyr::mutate(
      X = Hmisc::wtd.Ecdf(x_var)$x,
      Y = Hmisc::wtd.Ecdf(x_var)$ecdf
    )

Примите во внимание любые советы по отладке текущей попытки 'dplyr' или другого подхода, полностью использующего dplyr.

1 Ответ

1 голос
/ 01 мая 2019

Как насчет этого (также требуется tidyr, хотя)

dplyr_solution <- df_samp %>% 
  dplyr::select(levels, x_var) %>%
  dplyr::group_by(levels) %>%
  dplyr::do( X = wtd.Ecdf(.$x_var)$x, 
      Y = wtd.Ecdf(.$x_var)$ecdf) %>% 
  tidyr::unnest()

Вы не можете использовать mutate, поскольку, как сказано в ?mutate, mutate "сохраняет количество строк ввода"но вам нужно изменить количество строк

Редактировать: Просто подумайте об этом немного больше, вам не понадобится tidyr::unnest, если вы сделаете это:

dplyr_solution2 <- df_samp %>% 
  dplyr::select(levels, x_var) %>%
  dplyr::group_by(levels) %>%
  dplyr::do( data.frame(X = wtd.Ecdf(.$x_var)$x, 
             Y = wtd.Ecdf(.$x_var)$ecdf))

Редактировать нет2: Вы пишете, dplyr::do в основном обесценивается, я собирался предложить решение мурлыкания, но вы специально запросили dplyr.Я всегда предполагал, что group_map был частью мурлыкания (я думаю, что я обнаружил их одновременно).

Вы можете просто выложить do для group_map с очень незначительным изменением синтаксиса:

dplyr_solution3 <- df_samp %>% 
  dplyr::select(levels, x_var) %>%group_by(levels) %>% 
  dplyr::group_map(~data.frame(X = wtd.Ecdf(.$x_var)$x, 
                        Y = wtd.Ecdf(.$x_var)$ecdf))

Или вы можете переключиться на purrr::map_dfr

purrr_solution <- df_samp %>% 
  dplyr::select(levels, x_var) %>% 
  split(.$levels) %>% 
  purrr::map_dfr(~data.frame(X = wtd.Ecdf(.$x_var)$x, 
                               Y = wtd.Ecdf(.$x_var)$ecdf), .id = "levels")
...