2017-04-04 80 views
0

我有包含多项选择问题结果的数据框。每个项目有0(未提及)或1(提到)。列被命名为这样的:将分词列与分号分隔的列连接

F1.2_1, F1.2_2, F1.2_3, F1.2_4, F1.2_5, F1.2_99

我想串连这些值是这样的:新列应该是选择的项目以分号分隔的字符串。因此,如果F1.2_1,F1.2_4和F1.2_5中的某一行有1,则它应该是:1;4;5

dichotome列的最后一个数字是要在字符串中使用的项目代码。

任何想法如何用R(和data.table)实现这一点?谢谢你的帮助!

编辑

下面是一个例子DF与期望的结果:

structure(list(F1.2_1 = c(0L, 1L, 0L, 1L), F1.2_2 = c(1L, 0L, 
0L, 1L), F1.2_3 = c(0L, 1L, 0L, 1L), F1.2_4 = c(0L, 1L, 0L, 0L 
), F1.2_5 = c(0L, 0L, 0L, 0L), F1.2_99 = c(0L, 0L, 1L, 0L), desired_result = structure(c(3L, 
2L, 4L, 1L), .Label = c("1;2;3", "1;3;4", "2", "99"), class = "factor")), .Names = c("F1.2_1", 
"F1.2_2", "F1.2_3", "F1.2_4", "F1.2_5", "F1.2_99", "desired_result" 
), class = "data.frame", row.names = c(NA, -4L)) 




    F1.2_1 F1.2_2 F1.2_3 F1.2_4 F1.2_5 F1.2_99 desired_result 
1  0  1  0  0  0  0    2 
2  1  0  1  1  0  0   1;3;4 
3  0  0  0  0  0  1    99 
4  1  1  1  0  0  0   1;2;3 

回答

1

在他comment中,OP问如何应对更多的选择题。

下面的方法将能够处理每个问题的任意数量的问题和选择。它使用data.table包中的melt()dcast()

取样输入数据

假设输入data.frame DT的扩展情况下包含两个问题,一个有6个选择和其他4个选项:

DT 
# F1.2_1 F1.2_2 F1.2_3 F1.2_4 F1.2_5 F1.2_99 F2.7_1 F2.7_2 F2.7_3 F2.7_11 
#1:  0  1  0  0  0  0  0  1  1  0 
#2:  1  0  1  1  0  0  1  1  1  1 
#3:  0  0  0  0  0  1  1  0  1  0 
#4:  1  1  1  0  0  0  1  0  1  1 

代码

library(data.table) 

# coerce to data.table and add row number for later join 
setDT(DT)[, rn := .I] 

# reshape from wide to long format 
molten <- melt(DT, id.vars = "rn") 

# alternatively, the measure cols can be specified (in case of other id vars) 
# molten <- melt(DT, measure.vars = patterns("^F")) 

# split question id and choice id 
molten[, c("question_id", "choice_id") := tstrsplit(variable, "_")] 

# reshape only selected choices from long to wide format, 
# thereby pasting together the ids of the selected choices for each question 
result <- dcast(molten[value == 1], rn ~ question_id, paste, collapse = ";", 
       fill = NA, value.var = "choice_id") 

# final join for demonstration only, remove row number as no longer needed 
DT[result, on = "rn"][, rn := NULL][] 
# F1.2_1 F1.2_2 F1.2_3 F1.2_4 F1.2_5 F1.2_99 F2.7_1 F2.7_2 F2.7_3 F2.7_11 F1.2  F2.7 
#1:  0  1  0  0  0  0  0  1  1  0  2  2;3 
#2:  1  0  1  1  0  0  1  1  1  1 1;3;4 1;2;3;11 
#3:  0  0  0  0  0  1  1  0  1  0 99  1;3 
#4:  1  1  1  0  0  0  1  0  1  1 1;2;3 1;3;11 

对于每个问题,最终结果显示每行中选择了哪些选择。

重现数据

样本数据可以与

DT <- structure(list(F1.2_1 = c(0L, 1L, 0L, 1L), F1.2_2 = c(1L, 0L, 
0L, 1L), F1.2_3 = c(0L, 1L, 0L, 1L), F1.2_4 = c(0L, 1L, 0L, 0L 
), F1.2_5 = c(0L, 0L, 0L, 0L), F1.2_99 = c(0L, 0L, 1L, 0L), F2.7_1 = c(0L, 
1L, 1L, 1L), F2.7_2 = c(1L, 1L, 0L, 0L), F2.7_3 = c(1L, 1L, 1L, 
1L), F2.7_11 = c(0L, 1L, 0L, 1L)), .Names = c("F1.2_1", "F1.2_2", 
"F1.2_3", "F1.2_4", "F1.2_5", "F1.2_99", "F2.7_1", "F2.7_2", 
"F2.7_3", "F2.7_11"), row.names = c(NA, -4L), class = "data.frame") 
+0

哦,是的,非常好! – Mario

1

我们可以尝试

j1 <- do.call(paste, c(as.integer(sub(".*_", "", 
       names(DF)[-7]))[col(DF[-7])]*DF[-7], sep=";")) 

DF$newCol <- gsub("^;+|;+$", "", gsub(";*0;|0$|^0", ";", j1)) 
DF$newCol 
#[1] "2"  "1;3;4" "99" "1;2;3" 
+0

非常感谢创建,这与小例子效果很好 - 但是,在我的真实数据,有更多的列和不同的选择题的问题。例如,另外一个是“F2.7_1”,“F2.7_2”,“F2.7_3”,“F2.7_4”......还有一些是其他问题。任何想法如何可以纳入? – Mario

+0

@Mario在我的第一种方法中,我使用了列号,但是当您显示它是所需列名的最后一部分时,我对其进行了更改。不知道你想如何纳入 – akrun

+0

我在'data.table'中想到了这样的事情:'newCol = ifelse(F1.2_1 == 1,1,ifelse(F1.2_2,2,ifelse(F1.2_3) ,3,ifelse(F1.2_4,4,ifelse(F1.2_5,5,ifelse(F1.2_6,6,ifelse(F1.2_7,7,ifelse(F1.2_8,8,ifelse(F1.2_9,9 ,ifelse(F1.2_99,99,NA))))))))))' - 所以它是硬编码的,但是这个代码只会产生一个字符而不是一个; - 分离的。这可能以某种方式粘贴在一起 – Mario