【问题标题】:pmap purrr error: Argument 1 must have namespmap purrr 错误:参数 1 必须有名称
【发布时间】:2020-01-10 01:07:51
【问题描述】:

我计划按行对 data.table 求和并为其添加一个常数。这段代码有什么问题。我正在专门寻找 pmap_dfr 解决方案:

library(data.table)
library(tidyverse)
temp.dt <- data.table(a = 1:3, b = 1:3, c = 1:3)
d <- 10
temp.dt %>% pmap_dfr(., sum, d)   # add columns a b and c and add variable d to it

预期的输出是包含以下行的单列小标题:

13 16 19

抛出的错误:参数 1 必须有名称。

我已经能够让它与 pmap 和 pmap_dbl 一起使用,但是在使用 pmap_dfr 时它会失败。此外,我提供的示例是一个玩具示例。我希望 d 变量作为 sum 函数的输入参数,而不是稍后将 d 添加到逐行求和中。

例如,我知道下面会起作用:

temp.dt %>% pmap_dbl(., sum) + d

【问题讨论】:

    标签: r purrr pmap


    【解决方案1】:

    常规数据帧也会出现问题,因此为了将其简化为基本要素,请启动一个新的 R 会话,去掉 data.table 部分并使用显示的输入,其中我们有一个 3x4 data.frame,这样我们就不用了t 混淆行和列。另请注意,pmap_dfr(sum, d)pmap(sum, d) %&gt;% bind_rows 相同,并且问题发生在bind_rows 步骤中。

    library(dplyr)
    library(purrr)
    
    # test input
    temp.df <- data.frame(a = 1:3, b = 1:3, c = 1:3, z = 1:3)
    rownames(temp.df) <- LETTERS[1:3]
    d <- 10
    
    out <- temp.df %>% pmap(sum, d)     # this works
    out %>% bind_rows
    ## Error: Argument 1 must have names
    

    如错误所示,问题在于out 没有名称,而且它似乎不会为结果提供默认名称。例如,这将起作用——我并不是建议您一定要这样做,而只是试图通过显示使其起作用的最小更改来说明它为什么不起作用:

    temp.df %>% pmap(sum, d) %>% set_names(rownames(temp.df)) %>% bind_rows
    
    ## # A tibble: 1 x 3
    ##       A     B     C
    ##   <dbl> <dbl> <dbl>
    ## 1    14    18    22
    

    或者可以这样写以避免两次写temp.df

    temp.df %>% { set_names(pmap(., sum, d), rownames(.)) } %>% bind_rows
    

    我认为我们可以得出结论,pmap_dfr 不适合在这里使用。

    基础 R

    当然,这在基础 R 中都是微不足道的,因为您可以这样做:

    rowSums(temp.df) + d
    ##  A  B  C 
    ## 14 18 22 
    

    或更笼统地说:

    as.data.frame.list(apply(temp.df, 1, sum, d))
    ##  A  B  C 
    ## 14 18 22 
    

    as.data.frame.list(Reduce("+", temp.df) + d)
    ##   X14 X18 X22
    ##1  14  18  22
    

    数据表

    在data.table中我们可以写:

    library(data.table)
    
    DT <- as.data.table(temp.df)
    
    DT[, as.list(rowSums(.SD) + d)]
    ##    V1 V2 V3
    ## 1: 14 18 22
    
    DT[, as.list(apply(.SD, 1, sum, d))]
    ##    V1 V2 V3
    ## 1: 14 18 22
    

    还请注意,直接使用 data.table 往往比在其上添加另一个级别更快,因此,如果您认为通过将 data.table 与 dplyr 和 purrr 一起使用可以获得 data.table 的速度优势,那么您可能不会。

    【讨论】:

    • 谢谢!解释得很好。
    【解决方案2】:

    pmap_dfr 解决方案是首先transpose 数据集。我们稍后可以根据需要重命名列:

    temp.dt %>% 
     t() %>% 
       as.data.frame()-> tmp_dt
       pmap_dfr(list(tmp_dt, 10),sum)
    # A tibble: 1 x 3
         V1    V2    V3
      <dbl> <dbl> <dbl>
    1    13    16    19
    

    一个可能的dplyr-base 替代方案:

    temp.dt %>% 
       mutate(Sum = rowSums(.) + d) %>% 
      pull(Sum)
    [1] 13 16 19
    

    或者使用pmap_dbl:

    temp.dt %>% 
       pmap_dbl(.,sum) + d
    [1] 13 16 19
    

    【讨论】:

    • 我正在尝试学习使用 pmap。你知道如何使用 pmap_dfr 吗?
    • 我添加了一个pmap 替代方案。不过,使用map2imap 可能会更好。
    • 对不起,我正在寻找 pmap_dfr 。我已经能够让它与 pmap 和 pmap_dbl 一起使用,但是在使用 pmap_dfr 时它失败了。此外,我提供的示例是一个玩具示例。我希望 d 变量作为 sum 函数的输入参数,而不是稍后将 d 添加到逐行求和中。
    • 检查编辑。您可以根据需要重命名结果。
    猜你喜欢
    • 1970-01-01
    • 2018-07-08
    • 2019-03-01
    • 2021-09-14
    • 1970-01-01
    • 2021-06-21
    • 1970-01-01
    • 2017-06-11
    • 2021-10-15
    相关资源
    最近更新 更多