假设要求受访者(id)进行二元(离散)选择,请在五个任务中选择1或2(t = 1,2,3,4,5)(每个受访者具有五个观察值的面板数据)。
如果被访者选择了选项1,则结果为固定值(总是说30),但是如果被访者选择了选择2,则结果是不同的,并取决于被访者所处的治疗方式(只有一个每个响应者的治疗方法,因为仅将响应者随机分配给一种治疗)。假设有四种治疗方法(一种载体),并且如果选择了选择2,则每种治疗方法都有五种结果。
也就是说,
treat1 = 1,2,3,4,5
treat2 = 6,7,8,9,10
treat3 = 11,12,13,14,15
treat4 = 16,17,18,19,20
例如,对于 treat1 ,如果第一个任务中的受访者选择了选项2,则结果等于1。在第二个任务中,受访者选择了选项1,则结果是30(一如既往)。在第三项任务中,如果受访者选择选项2,则结果为2(而不是3)。也就是说,如果在treat1中第一次选择了选项2,则从treat1序列中选择第一个值;如果在treat1中第二次选择了选项2,则从treat 2序列中选择第二个值,依此类推。
结果如下所示。
+----+---+-----------+--------+---------+
| id | t | treatment | choice | outcome |
+----+---+-----------+--------+---------+
| 1 | 1 | 1 | 2 | 1 |
| 1 | 2 | 1 | 1 | 30 |
| 1 | 3 | 1 | 2 | 2 |
| 1 | 4 | 1 | 1 | 30 |
| 1 | 5 | 1 | 2 | 3 |
| 2 | 1 | 3 | 1 | 30 |
| 2 | 2 | 3 | 2 | 11 |
| 2 | 3 | 3 | 2 | 12 |
| 2 | 4 | 3 | 1 | 30 |
| 2 | 5 | 3 | 2 | 13 |
| 3 | 1 | 2 | 2 | 6 |
| 3 | 2 | 2 | 1 | 30 |
| 3 | 3 | 2 | 1 | 30 |
| 3 | 4 | 2 | 1 | 30 |
| 3 | 5 | 2 | 2 | 7 |
| 4 | 1 | 4 | 1 | 30 |
| 4 | 2 | 4 | 1 | 30 |
| 4 | 3 | 4 | 1 | 30 |
| 4 | 4 | 4 | 2 | 16 |
| 4 | 5 | 4 | 1 | 30 |
| 5 | 1 | 2 | 1 | 30 |
| 5 | 2 | 2 | 1 | 30 |
| 5 | 3 | 2 | 1 | 30 |
| 5 | 4 | 2 | 1 | 30 |
| 5 | 5 | 2 | 2 | 6 |
| . | . | . | . | . |
| . | . | . | . | . |
| . | . | . | . | . |
| . | . | . | . | . |
| . | . | . | . | . |
+----+---+-----------+--------+---------+
由于我的数据有成千上万的观察值,所以我想知道哪种有效的方法来生成变量结果。
id , t ,治疗和 choice 变量在我的数据集中可用。
任何想法都将不胜感激。谢谢。
答案 0 :(得分:3)
另一种可能的方法是将处理方法组织到data.table中,然后进行联接并在choice = 2时通过引用进行更新
#the sequence of treatment when choice==2
DT[choice==2, ri := rowid(id)]
#look up treatment for the sequence
DT[choice==2, outcome := treat[.SD, on=.(treatment, ri), val]]
#set outcome to 30 for choice=1
DT[choice==1, outcome := 30]
#delete column
DT[, ri := NULL]
数据:
library(data.table)
treat <- data.table(treatment=rep(1:4, each=5),
ri=rep(1:5, times=4),
val=1:20)
DT <- fread("id,t,treatment,choice,outcome
1,1,1,2,1
1,2,1,1,30
1,3,1,2,2
1,4,1,1,30
1,5,1,2,3")
DT[, outcome := NULL]
答案 1 :(得分:1)
您没有提供任何示例数据,因此我先创建一些虚假数据
数据
set.seed(1)
treat_lkp <- list(trt1 = 1:5, trt2 = 6:10, trt3 = 11:15, trt4 = 16:20)
d_in <- expand.grid(task = 1:5, id = 1:5)
d_in$treatment <- paste0("trt", d_in$id %% 4 + 1)
d_in$choice <- sample(2, NROW(d_in), TRUE)
tidyverse解决方案
我使用一个简单的tidyverse
解决方案。
library(purrr)
library(dplyr)
d_out <- d_in %>%
group_by(id) %>%
mutate(task_new = cumsum(choice == 2)) %>%
ungroup() %>%
mutate(outcome = {
l <- treat_lkp[as.character(d_in$treatment)]
pmap_dbl(list(task = task_new, choice = choice, set = l),
function(task, choice, set)
ifelse(choice == 1, 30, set[task])
)}
)
head(d_out)
# # A tibble: 6 x 6
# task id treatment choice task_new outcome
# <int> <int> <chr> <int> <int> <dbl>
# 1 1 1 trt2 1 0 30
# 2 2 1 trt2 1 0 30
# 3 3 1 trt2 2 1 6
# 4 4 1 trt2 2 2 7
# 5 5 1 trt2 1 2 30
# 6 1 2 trt3 2 1 11
说明
您首先创建一个列表l
,其中包含与您的结果相关的查找值(取决于treatment
)。然后,您在task
,treatment
和choice
上循环选择30
(对于choice == 1
)或使用来自l
的正确查找值
更新
考虑到注释后,我们现在首先需要创建一个task_new
变量来保持正确的位置。那是第一个choice == 2
应该导致1
到第二个2
,依此类推。因此,我们group_by
id
并通过cumsum
添加计数器。取消分组数据后,我们在task_new
调用中使用mutate
。