R:对具有不同后缀的向量应用操作

时间:2017-07-10 17:39:21

标签: r

我必须在很少的向量和行上执行一些简单的操作。

假设我有一个数据库,例如:

observation      outcome_1_a   outcome_2_a   outcome_1_b   outcome_2_b choice_a choice_b 
1                41            34            56            19          1        1 
2                32            78            43            6           2        1
3                39            19            18            55          1        2

对于每个观察,outcome_1和outcome_2是两个可能的结果,choice是选择的结果,前缀_i,i = a,b,表示情境重复的次数。

如果我想创建存储每个情况的最高结果的变量(a,b),那么:

max.a <- pmax(data$outcome_1_a, data$outcome_2_a)
max.b <- pmax(data$outcome_1_b, data$outcome_2_b)

同样,如果我想创建存储在每个情境中选择的值的变量,我可以这样做:

choice.a <- ifelse(data$choice_a == "1", data$outcome_1_a, data$outcome_1_b)
choice.b <- ifelse(data$choice_b == "1", data$outcome_2_a, data$outcome_2_b)

最后,如果我想计算情境 a和b的行的平均值,我可以这样做:

library(data.table)
setDT(data)
data[, .(Mean = rowMeans(.SD)), by = observation, .SDcols = c("outcome_1_a","outcome_2_a", "outcome_1_b", "outcome_2_b")]

现在,所有这些工作都很好。但是,我想知道是否可以以更有效的方式完成此类操作。

在示例中只有少数情境,但是,如果将来我将不得不处理,比方说,15个或更多不同的情况(a,b,c,d, ......,),写这样的操作可能很烦人。

有没有办法根据变量的不同前缀和/或后缀自动执行此类过程?

感谢您的帮助

2 个答案:

答案 0 :(得分:1)

您可以选择带有一些正则表达式的列。例如,要获取max.a值。

library(data.table)

setDT(data)
data[, do.call(pmax, .SD), .SDcols = names(data) %like% "\\d+_a$"]

[1] 41 78 39

或者,您可以在data.table之外的某些正则表达式中选择列。有很多方法可以解决这个问题。

与上一个命令类似的应用程序。

data[, 
     .(Mean = rowMeans(.SD)), 
     by = observation, 
     .SDcols = names(data) %like% "^outcome"]
   observation  Mean
1:           1 37.50
2:           2 39.75
3:           3 32.75

对于choice.a,您如何在b,c,d,e等之间进行选择?

答案 1 :(得分:1)

例如:

outcome_1_a outcome_2_a outcome_1_b outcome_2_b outcome_1_c outcome_2_c outcome_1_d outcome_2_d outcome_1_e outcome_2_e choice_a choice_b choice_c choice_d choice_e
        <dbl>       <dbl>       <dbl>       <dbl>       <dbl>       <dbl>       <dbl>       <dbl>       <dbl>       <dbl>    <dbl>    <dbl>    <dbl>    <dbl>    <dbl>
1          12          85          32          28          91          42          32          96          27          29        2        1        1        1        1
2          17          22          84          53          11          69          16          66          11          41        1        2        2        1        1
3          92          98          76          83          18          27          21          51          92          41        1        1        1        1        2
4          63          49          61          64         100          28          43          51          22          94        1        2        1        1        1

定义一个可帮助您完成循环的索引变量:

seqmax <- seq(1, 10, by = 2)

seqmax1 3 5 7 9。原因是有5个字母"a" "b" "c" "d" "e"。所以这个序列将帮助你模式化循环。这可以针对最大字母数自动执行,只需找到choice_a之前的最后一列的列索引。然后你可以做seq(1, grep(names(data), pattern = "choice_a") - 1, by = 2)。可以按字母为列数调整by = 2参数。

我将lapply<<-一起用于将新列添加到data

lapply(c(1:5), function(x){

  data[, paste0("max.", letters[x])] <<- apply(data[, c(seqmax[x], seqmax[x] + 1)], 1, max)

  data[, paste0("choice.", letters[x])] <<- ifelse(
    data[, grep(names(data), pattern = paste0("choice_", letters[x]), value = T)] == 1,
  data[, seqmax[x]], data[, seqmax[x] + 1])

  data[, paste0("mean.", letters[x])] <<- rowMeans(
    data[, grep(names(data), pattern = paste0("outcome_\\d+_", letters[x]), value = T)])

})