R - 如何根据包含要用于操作的列的名称的额外列对每一行的不同列进行操作

R - How to operate on different columns for each row based on an extra-column containing the names of the columns to be used for operation

我是 R 的新手。我想计算数据框每一行的平均值,但对每一行使用不同的列子集。我有两个额外的列,分别为我提供了代表“开始”和“结束”的列的名称,我应该使用它们来计算每个平均值。

举个例子

dframe <- data.frame(a=c("2","3","4", "2"), b=c("1","3","6", "2"), c=c("4","5","6", "3"), d=c("4","2","8", "5"), e=c("a", "c", "a", "b"), f=c("c", "d", "d", "c"))
dframe

提供以下数据框:

  a b c d e f
1 2 1 4 4 a c
2 3 3 5 2 c d
3 4 6 6 8 a d
4 2 2 3 5 b c

列 e 和 f 代表我用来计算每行平均值的第一列和最后一列。 例如,在第 1 行,将计算平均值,包括 a、b、c 列 ((2+1+4)/3 -> 2.3) 所以我想获得以下输出:

  a b c d e f mean
1 2 1 4 4 a c  2.3
2 3 3 5 2 c d  3.5
3 4 6 6 8 a d    6
4 2 2 3 5 b c  2.5

我学会了如何创建索引,然后我想使用 RowMeans,但找不到正确的参数。

dframe %>%
  mutate(e_indice = match(e, colnames(dframe)))%>%
  mutate(f_indice = match(f, colnames(dframe)))%>%
  mutate(mean = RowMeans(????, na.rm = TRUE))

非常感谢您的帮助

一个dplyr选项可以是:

dframe %>%
    rowwise() %>%
    mutate(mean = rowMeans(cur_data()[match(e, names(.)):match(f, names(.))]))

      a     b     c     d e     f      mean
  <dbl> <dbl> <dbl> <dbl> <chr> <chr> <dbl>
1     2     1     4     4 a     c      2.33
2     3     3     5     2 c     d      3.5 
3     4     6     6     8 a     d      6   
4     2     2     3     5 b     c      2.5 

我会定义一个辅助函数,让你可以切片你想要的索引 来自矩阵。

rowSlice <- function(x, start, stop) {
  replace(x, col(x) < start | col(x) > stop, NA)
}

rowSlice(matrix(1, 4, 4), c(1, 3, 1, 2), c(3, 4, 4, 3))
#>      [,1] [,2] [,3] [,4]
#> [1,]    1    1    1   NA
#> [2,]   NA   NA    1    1
#> [3,]    1    1    1    1
#> [4,]   NA    1    1   NA

然后使用 across() 到 select 相关列,将它们切片, 并采取 rowMeans().

library(dplyr)

dframe <- data.frame(
  a = c(2, 3, 4, 2),
  b = c(1, 3, 6, 2),
  c = c(4, 5, 6, 3),
  d = c(4, 2, 8, 5),
  e = c("a", "c", "a", "b"),
  f = c("c", "d", "d", "c")
)

dframe %>%
  mutate(ei = match(e, colnames(dframe))) %>%
  mutate(fi = match(f, colnames(dframe))) %>% 
  mutate(
    mean = across(a:d) %>%
      rowSlice(ei, fi) %>%
      rowMeans(na.rm = TRUE)
  )
#>   a b c d e f ei fi     mean
#> 1 2 1 4 4 a c  1  3 2.333333
#> 2 3 3 5 2 c d  3  4 3.500000
#> 3 4 6 6 8 a d  1  4 6.000000
#> 4 2 2 3 5 b c  2  3 2.500000

基础 R 解决方案。首先,将列设置为数字。然后创建要应用平均值的列的列表。然后对选定的列应用均值。

s <- mapply(seq, match(dframe$e, colnames(dframe)), match(dframe$f, colnames(dframe)))
dframe$mean <- lapply(seq(nrow(dframe)), function(x) rowMeans(dframe[x, s[[x]]]))

  a b c d e f     mean
1 2 1 4 4 a c 2.333333
2 3 3 5 2 c d      3.5
3 4 6 6 8 a d        6
4 2 2 3 5 b c      2.5

使用 apply

base R 方法
dframe$mean <- apply(dframe, 1, function(x) 
  mean(as.numeric(x[which(names(x) == x["e"]) : which(names(x) == x["f"])])))

dframe
  a b c d e f     mean
1 2 1 4 4 a c 2.333333
2 3 3 5 2 c d 3.500000
3 4 6 6 8 a d 6.000000
4 2 2 3 5 b c 2.500000