4

我正在将一项纵向研究的回答制成表格,在该研究中,参与者被要求自愿回答 4 项调查。每个参与者都有一个唯一的 PartID。每个参与者都被分配了一个 SectionID(字母)。已尝试并已完成的调查由 StatusID="Complete" 指示。已尝试但未完成的调查由 StatusID="Incomplete" 指示。未尝试调查的参与者将没有记录,但在结果列表中将该调查计为“0”。

输入数据示例:

    PartID SectionID     Status SurveyID
 1:    100         A   Complete        1
 2:    100         A   Complete        2
 3:    100         A   Complete        3
 4:    100         A   Complete        4
 5:    101         B Incomplete        1
 6:    101         B   Complete        2
 7:    101         B   Complete        3
 8:    101         B   Complete        4
 9:    102         A Incomplete        1
10:    103         B Incomplete        4
11:    104         B Incomplete        2
12:    105         A   Complete        1
13:    105         A   Complete        1
14:    105         A   Complete        3

以下代码有效,但非常草率。我假设有一种更简洁、更优雅的方式来使用 data.table 来完成这种数据处理?特别是,我想避免临时变量,以及合并两个 data.tables 的需要。

library(data.table)
DT <- fread ("PartID,SectionID,Status,SurveyID
100,A,Complete,1
100,A,Complete,2
100,A,Complete,3
100,A,Complete,4
101,B,Incomplete,1
101,B,Complete,2
101,B,Complete,3
101,B,Complete,4
102,A,Incomplete,1
103,B,Incomplete,4
104,B,Incomplete,2
105,A,Complete,1
105,A,Complete,1
105,A,Complete,3\n")

setkey(DT, PartID)

DT2<-DT
setkey(DT2,PartID, SectionID)
DT2<-DT2[Status=="Complete",.(c1=sum(SurveyID==1),c2=sum(SurveyID==2),c3=sum(SurveyID==3), c4=sum(SurveyID==4)), by=.(PartID,SectionID)]
DT3<-DT
setkey(DT3,PartID, SectionID)
DT3<-DT3[Status=="Incomplete",.(i1=sum(SurveyID==1),i2=sum(SurveyID==2),i3=sum(SurveyID==3), i4=sum(SurveyID==4)), by=.(PartID,SectionID)]
DT4<-merge(DT2,DT3, all=TRUE )
DT4[is.na(DT4)] <- 0
DT4

上面代码实现的输出是正确的,并且是(注意:c1 表示已完成调查#1,i1 表示调查#1 不完整。另请注意,参与者每次调查可以提交多个回复):

   PartID SectionID c1 c2 c3 c4 i1 i2 i3 i4
1:    100         A  1  1  1  1  0  0  0  0
2:    101         B  0  1  1  1  1  0  0  0
3:    102         A  0  0  0  0  1  0  0  0
4:    103         B  0  0  0  0  0  0  0  1
5:    104         B  0  0  0  0  0  1  0  0
6:    105         A  2  0  1  0  0  0  0  0
4

2 回答 2

3

你可以使用dcast

library(data.table)#v1.9.5+
dcast(DT[, N :=.N,list(PartID, SectionID, SurveyID)][,
        Status1:= paste0(tolower(substr(Status,1,1)), SurveyID)], 
        PartID+SectionID~Status1, value.var='N', length)
#   PartID SectionID c1 c2 c3 c4 i1 i2 i4
#1:    100         A  1  1  1  1  0  0  0
#2:    101         B  0  1  1  1  1  0  0
#3:    102         A  0  0  0  0  1  0  0
#4:    103         B  0  0  0  0  0  0  1
#5:    104         B  0  0  0  0  0  1  0
#6:    105         A  2  0  1  0  0  0  0

如果您需要i3

DT1 <- DT[, N :=.N,list(PartID, SectionID, SurveyID)][,
    Status1:= paste0(tolower(substr(Status,1,1)), SurveyID)]
DT2 <- data.table(Status1=paste0(rep(c('c', 'i'),each=4), 1:4))
 na.omit(dcast(setkey(DT1, Status1)[DT2], 
      PartID+SectionID~Status1, value.var='N', length))
 #   PartID SectionID c1 c2 c3 c4 i1 i2 i3 i4
 #1:    100         A  1  1  1  1  0  0  0  0
 #2:    101         B  0  1  1  1  1  0  0  0
 #3:    102         A  0  0  0  0  1  0  0  0
 #4:    103         B  0  0  0  0  0  0  0  1
 #5:    104         B  0  0  0  0  0  1  0  0
 #6:    105         A  2  0  1  0  0  0  0  0
于 2015-04-18T14:45:04.663 回答
3

另一个不会改变您的DT-Table 的解决方案是:

dt2 <- DT[,.(.N), by=.(PartID,SectionID, SurveyID, Status)]
dcast.data.table(dt2,PartID + SectionID ~ Status + SurveyID, value.var='N', sum)

导致

   PartID SectionID Complete_1 Complete_2 Complete_3 Complete_4 Incomplete_1 Incomplete_2 Incomplete_4
1:    100         A          1          1          1          1            0            0            0
2:    101         B          0          1          1          1            1            0            0
3:    102         A          0          0          0          0            1            0            0
4:    103         B          0          0          0          0            0            0            1
5:    104         B          0          0          0          0            0            1            0
6:    105         A          2          0          1          0            0            0            0

akrun 的解决方案还展示了如何在需要时重命名列。

于 2015-04-18T14:53:03.063 回答