【问题标题】:Code not working using map from purrr package in R代码无法使用 R 中 purrr 包中的地图工作
【发布时间】:2018-02-11 00:53:09
【问题描述】:

我正在学习 purrr 包中的地图功能,但以下代码不起作用:

library(purrr)
library(dplyr)

df1 = data.frame(type1 = c(rep('a',5),rep('b',5)),
             x = 1:10,
             y = 11:20) 

df1 %>% 
  group_by(type1) %>% 
  nest() %>% 
  map(.$data,with(.x, x + y))

df1 %>% 
  group_by(type1) %>% 
  nest() %>% 
  map(.$data,function(df) df$x + df$y)

对于最后两个代码块,错误返回为:

错误:索引 1 的长度必须为 1

相反,以下两段代码运行良好,

df1 %>% 
  group_by(type1) %>% 
  nest() %>% .$data %>% 
  map(.,~with(.x, .x$x + .x$y))


df1 %>% 
  group_by(type1) %>% 
  nest() %>% .$data %>% 
  map(.,~with(.x, .x$x + .x$y))

谁能帮我理解错误以及如何修复它们?

【问题讨论】:

  • 为什么要group_by() %>% nest()?是否可以使用split() 代替?
  • 您是否有一个特定的用例?在这里,df1 %>% group_by(type1) %>% mutate(sumxy = x + y) 似乎是要走的路。
  • @eipi10,感谢您的帮助!实际的功能比这里的加号操作要复杂得多....
  • @NateDay,感谢您的帮助!拆分绝对是一种选择,在这里我只想了解如何使用 purrr 包中的地图

标签: r dplyr purrr


【解决方案1】:

如果你想使用split(),我通常会拆分我的分组因子,然后只映射一个匿名函数来为新创建的列表中的单个小标题/数据框做些什么:

df1 %>% 
    split(.$type1) %>% 
    map(~ mutate(., z = x + y) %>% # chain like you would a single tib
        select(z) %>%
        unlist(T,F))
$a
[1] 12 14 16 18 20

$b
[1] 22 24 26 28 30

【讨论】:

    【解决方案2】:

    您需要在 map 表达式周围添加大括号,因为 . 在函数中不会作为单独的参数占位符出现,因此 magrittr 管道正在应用 first-argument规则 您可以阅读更多关于here 的信息;并使用~ 构造一个函数,这是map 所期望的:

    df1 %>% 
        group_by(type1) %>% 
        nest() %>% 
        { map(.$data, ~ with(.x, x + y)) }
    
    #[[1]]
    #[1] 12 14 16 18 20
    
    #[[2]]
    #[1] 22 24 26 28 30
    

    第二种方法也一样:

    df1 %>% 
        group_by(type1) %>% 
        nest() %>% 
        { map(.$data,function(df) df$x + df$y) }
    #[[1]]
    #[1] 12 14 16 18 20
    
    #[[2]]
    #[1] 22 24 26 28 30
    

    【讨论】:

    • 感谢您的帮助,代码有效!您能否详细说明为什么没有括号代码不起作用? .$data 是一个列表,应该与 map 函数一起使用。另一方面,如果我用 lapply 替换 map 函数,代码也可以工作。为什么地图的工作方式与 lapply 不同?
    • 没有{},由于第一个参数规则,您的代码等效于map(., .$data, ~with(.x, x+y)),这是map函数的不正确语法。此外,你是如何得到lapply 工作的?在我看来,您仍然需要大括号 lapply 才能正常工作;
    • 你说得对,除非我使用 ".$data" 提取数据并使用另一个 %>% 运算符,否则 lapply 将无法直接工作。那么如何在不使用花括号的情况下将第一个参数分配给 .$data 呢?我试过 .x = .$data 但它不起作用....
    • 我认为你必须使用{} 来避免%>% 将另一个. 作为参数传递给map。据我所知,只要它没有找到 . 作为参数,就无法通过使用命名参数来阻止它这样做。
    • 好吧,我还是坚持{}吧,看来使用“with”达到和{}一样的效果,这里的{}和“with”有什么区别吗?这是我第一次使用{},我想了解这个运算符。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-07-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-28
    • 1970-01-01
    相关资源
    最近更新 更多