根据预定义向量和离散结果中的数据创建变量

时间:2019-05-14 08:06:31

标签: r dplyr data.table

假设要求受访者(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 变量在我的数据集中可用。

任何想法都将不胜感激。谢谢。

2 个答案:

答案 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)。然后,您在tasktreatmentchoice上循环选择30(对于choice == 1)或使用来自l的正确查找值

更新

考虑到注释后,我们现在首先需要创建一个task_new变量来保持正确的位置。那是第一个choice == 2应该导致1到第二个2,依此类推。因此,我们group_by id并通过cumsum添加计数器。取消分组数据后,我们在task_new调用中使用mutate