我必须在很少的向量和行上执行一些简单的操作。
假设我有一个数据库,例如:
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, ......,),写这样的操作可能很烦人。
有没有办法根据变量的不同前缀和/或后缀自动执行此类过程?
感谢您的帮助
答案 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)
seqmax
是1 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)])
})