pmap purrr 错误:参数1必须具有名称

3
我计划逐行对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

期望的输出是一个单列的tibble,包含以下行:

13 16 19

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

我已经可以使用pmap和pmap_dbl使其工作,但在使用pmap_dfr时失败了。此外,我提供的示例只是一个玩具示例。我想要将d变量作为sum函数的输入参数,而不是后来将d添加到逐行求和中。

我知道下面的示例会起作用:

temp.dt %>% pmap_dbl(., sum) + d
2个回答

5
问题也会出现在普通的数据框中,因此为了将其简化至要点,重新开始一个R会话,去掉data.table的部分,并使用所示的输入,其中我们有一个3x4的数据框,这样我们就不会混淆行和列。还要注意,pmap_dfr(sum, d)pmap(sum, d) %>% 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

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

在 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往往比在其之上增加另一层更快,因此,如果您认为通过将其与dplyr和purrr一起使用可以获得data.table速度的好处,那么您可能不是这样。


谢谢!讲解得非常好。 - aajkaltak

2

pmap_dfr 的解决方案是首先将数据集进行转置。稍后我们可以根据需要重新命名列:

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

1
我正在尝试学习使用pmap。您知道如何使用pmap_dfr吗? - aajkaltak
我已经添加了一个pmap的替代方案。不过你可能更适合使用map2imap - NelsonGon
1
抱歉,我正在寻找pmap_dfr。我已经成功地使用pmap和pmap_dbl,但是在使用pmap_dfr时失败了。此外,我提供的示例只是一个玩具示例。我希望将d变量作为输入参数传递给sum函数,而不是稍后将d添加到按行求和中。 - aajkaltak
检查编辑。您可以根据需要重命名结果。 - NelsonGon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接