使用 dplyr 将函数应用于 data.frame 中的一行

tho*_*hal 8 r dplyr purrr tidyverse

在基地R我会做以下事情:

d <- data.frame(a = 1:4, b = 4:1, c = 2:5)
apply(d, 1, which.max)
Run Code Online (Sandbox Code Playgroud)

随着dplyr我可以做到以下几点:

library(dplyr)
d %>% mutate(u = purrr::pmap_int(list(a, b, c), function(...) which.max(c(...))))
Run Code Online (Sandbox Code Playgroud)

如果d我需要指定另一列,但我希望它可以使用任意数量的列。

从概念上讲,我想要类似的东西

pmap_int(list(everything()), ...)
pmap_int(list(.), ...)
Run Code Online (Sandbox Code Playgroud)

但这显然行不通。我将如何规范地解决这个问题dplyr

akr*_*run 7

我们只需要被指定为数据.data.framelist与作为列表元素列。如果我们 wrap list(.),它将成为一个嵌套列表

library(dplyr)
d %>% 
  mutate(u = pmap_int(., ~ which.max(c(...))))
#  a b c u
#1 1 4 2 2
#2 2 3 3 2
#3 3 2 4 3
#4 4 1 5 3
Run Code Online (Sandbox Code Playgroud)

或者可以使用 cur_data()

d %>%
   mutate(u = pmap_int(cur_data(), ~ which.max(c(...))))
Run Code Online (Sandbox Code Playgroud)

或者,如果我们想使用everything(),将它放在里面selectaslist(everything())不解决应该从中选择所有内容的数据

d %>% 
   mutate(u = pmap_int(select(., everything()), ~ which.max(c(...))))
Run Code Online (Sandbox Code Playgroud)

或使用 rowwise

d %>%
    rowwise %>% 
    mutate(u = which.max(cur_data())) %>%
    ungroup
# A tibble: 4 x 4
#      a     b     c     u
#  <int> <int> <int> <int>
#1     1     4     2     2
#2     2     3     3     2
#3     3     2     4     3
#4     4     1     5     3
Run Code Online (Sandbox Code Playgroud)

或者这更有效 max.col

max.col(d, 'first')
#[1] 2 2 3 3
Run Code Online (Sandbox Code Playgroud)

或与 collapse

library(collapse)
dapply(d, which.max, MARGIN = 1)
#[1] 2 2 3 3
Run Code Online (Sandbox Code Playgroud)

可以包含在dplyr作为

d %>% 
    mutate(u = max.col(cur_data(), 'first'))
Run Code Online (Sandbox Code Playgroud)

  • 哈哈,我在这里忘记了`data.table`。谢谢提醒!我补充说:) (2认同)