【问题标题】:Replacing dplyr::do function with dplyr::group_split and purrr::map_df用 dplyr::group_split 和 purrr::map_df 替换 dplyr::do 函数
【发布时间】:2019-07-18 13:56:39
【问题描述】:

我正在寻找替换我的一些使用 dplyr::do 的 R 代码,因为这个函数很快就会被弃用。我的很多工作都需要创建分层的 CDF 图。使用 dply:do 时,我分层的变量作为变量传递给结果数据框,然后我可以轻松地使用它进行绘图。

我有一个使用 dplyr::group_split 和 purrr::map_df 替换 dplyr::do 的解决方案。但是,我在 dplyr::group_split 中传递的变量未在结果数据框中命名。这使得绘制分层数据变得困难。如何确保我在 dlyr::group_split 中传递的变量在结果数据框中命名?

这是一些创建我需要用 dplyr::do: 绘制的数据的代码:

library(dplyr)
library(purrr)
library(ggplot2)

# simulate data
dat <- tibble(
  strat = rep(letters[1:3], each = 33), 
  var   = rnorm(99, 0, 1))

# example 1 that works, but will be depricated 
test_dat_1 <- dat %>% 
  dplyr::select(strat, var) %>%
  dplyr::group_by(strat) %>%
  dplyr::do(data.frame(X = wtd.Ecdf(.[[2]])$x, 
                       Y = wtd.Ecdf(.[[2]])$ecdf*100))

# this is the target plot
p <- ggplot(test_dat_1, aes(X, Y, colour = strat))
p + geom_step()

这是使用新的 tidy 和 purrr 函数创建数据的解决方案,但受限于最终数据框中未提供我要分层的变量,这使得绘制分层数据很麻烦:

# replacement for 'do'
test_dat_2 <- dat %>%
  group_split(strat) %>%
  map_df(~wtd.Ecdf(.x$var),
         tibble::enframe(name = "X", value = "Y"))

【问题讨论】:

  • 我也遇到过这种事情。一种选择是切换到group_nest() 之类的东西。由于split() 命名输出列表,您可以使用它来代替group_split()。一个简单的例子:dat %&gt;% split(.$strat) %&gt;% map_df(~data.frame(X = mean(.x$var) ), .id = "strat")

标签: r dplyr purrr


【解决方案1】:

假设wtd.Ecdf来自Hmisc,则输出为namedlist,可以用as_tibble转换成两列数据集,修改'ecdf'列如@987654328 @解决方案mutate

library(dplyr)
library(purrr)
library(Hmisc)
library(ggplot2)
test_dat_2 <- dat %>% 
                 group_split(strat) %>% 
                 map_df(~ c(strat = first(.x$strat), wtd.Ecdf(.x$var)) %>% 
                              as_tibble %>%
                              mutate(ecdf = ecdf * 100)) %>%
                 rename_at(2:3, ~ c("X", "Y"))

现在,在绘图中使用它

p <- ggplot(test_dat_2, aes(X, Y, colour = strat))
p + geom_step()

-输出


一个选项也是在nesting 之后执行此操作

test_dat_3 <- dat %>%
                group_by(strat) %>%
                nest() %>% 
                mutate(out = map(data, ~ wtd.Ecdf(.x$var) %>% 
                          as_tibble)) %>% 
                select(-data) %>%
                unnest %>% 
                rename_at(2:3, ~c("X", "Y"))

【讨论】:

    【解决方案2】:

    拆分的另一种选择是嵌套group_nest()。嵌套后,您在mutate() 中执行map()

    如果您想将所有组绘制在一起,您可以 unnest(),来自 tidyr

    我在map() 中编写了一个匿名函数,而不是使用波浪号。

    dat %>%
        group_nest(strat) %>%
        mutate(result = map(data, function(dat) {
            res = Hmisc::wtd.Ecdf(dat$var)
            data.frame(X = res$x, Y = res$ecdf*100)
            }) ) %>%
        tidyr::unnest(result)
    
    # A tibble: 102 x 4
       strat data                   X     Y
       <chr> <list>             <dbl> <dbl>
     1 a     <tibble [33 x 1]> -1.88   0   
     2 a     <tibble [33 x 1]> -1.88   3.03
     3 a     <tibble [33 x 1]> -1.76   6.06
     4 a     <tibble [33 x 1]> -1.17   9.09
    ...
    

    您可以在取消嵌套之前在 mutate() 调用中根据需要使用 select()data = NULL 删除 data 列。

    【讨论】:

    • 两个答案都有效,我非常感谢两位受访者的反馈。我选择这个作为答案,因为它涉及的步骤更少。
    猜你喜欢
    • 1970-01-01
    • 2018-07-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多