根据列名向量选择正确的列

Choosing the right column based on a vector of column names

我正在尝试根据向量中的值从列中提取值。我不确定我用正确的词来描述问题,但代码应该有所帮助。

这感觉与 coalesce 可能不相关?

library(tidyverse)
# Starting table

dat <- 
tibble(
  A = 1:10,
  B = 31:40,
  C = 101:110,
  value = c("A", "C", "B", "A", "B", "C", "C", "B", "A", "A")
)

我要:

dat %>%
  mutate(
    output = c(1, 102, 33, 4, 35, 106, 107, 38, 9, 10)
  )

我可以

dat %>% 
  mutate(
    output = 
      case_when(value == "A" ~ A,
                value == "B" ~ B,
                value == "C" ~ C)
  )

但我的实际应用程序有很多值,我想利用具有匹配信息的值

是否有功能可以做到:

dat %>%
mutate(output = grab_the_right_column(value))

谢谢!

rowwise 方法效率较低,但它在 tidyverse 方法中是紧凑的get 基于每行的列名的列值。

library(dplyr)
dat %>% 
   rowwise %>%
   mutate(output = get(value)) %>%
   ungroup

-输出

# A tibble: 10 x 5
#       A     B     C value output
#   <int> <int> <int> <chr>  <int>
# 1     1    31   101 A          1
# 2     2    32   102 C        102
# 3     3    33   103 B         33
# 4     4    34   104 A          4
# 5     5    35   105 B         35
# 6     6    36   106 C        106
# 7     7    37   107 C        107
# 8     8    38   108 B         38
# 9     9    39   109 A          9
#10    10    40   110 A         10

使用 base R 中的 row/column 索引方法可以更有效地解决此类问题。使用 'value' 列和列名创建行序列的 matrix 和列的 matching 索引以提取元素

dat$output <- as.data.frame(dat)[,1:3][cbind(seq_len(nrow(dat)), match(dat$value, names(dat)[1:3]))]

你也可以使用 purrr 和 pmap():

library(dplyr)
library(purrr)

dat%>%mutate(output=
        pmap(., ~{
                v1<-c(...)
                v1[names(v1)==v1[['value']]]
                }
             )%>%
        as.numeric()%>%
        unlist)

# A tibble: 10 x 5
       A     B     C value output
   <int> <int> <int> <chr>  <dbl>
 1     1    31   101 A          1
 2     2    32   102 C        102
 3     3    33   103 B         33
 4     4    34   104 A          4
 5     5    35   105 B         35
 6     6    36   106 C        106
 7     7    37   107 C        107
 8     8    38   108 B         38
 9     9    39   109 A          9
10    10    40   110 A         10