我有一个调查数据框,其中包含对三个类别的评估。我确实希望在每一列中看到对每个类别的评估,但是这样混杂在一起,
ID q1 q2 q3 q4 q5 q6
1 c2 e1 c1 e1 c3 e2
2 c1 e1 c3 e2 c2 e0
3 c3 e0 c2 e2 c1 e1
我想要得到的是:
ID c1 c2 c3
1 e1 e1 e2
2 e1 e0 e2
3 e1 e2 e0
但是,尝试通过stringr和dplyr几种方法,现在我只是停留在这里:
ID a1 a2 a3
1 c1-e1 c2-e1 c3-e2
2 c1-e1 c2-e0 c3-e2
3 c1-e1 c2-e2 c3-e0
有人知道如何解决此问题吗?预先谢谢你!
答案 0 :(得分:2)
我们可以使用split
根据列名分隔列中的值。
如果列数有限,则可以像我一样手动创建列,或者根据列的结构使用paste
和seq
以编程方式进行列。
cols <- c("q1", "q3", "q5")
vals <- c("q2", "q4", "q6")
do.call("cbind.data.frame", split(unlist(df[vals]), unlist(df[cols])))
# c1 c2 c3
#q22 e1 e1 e0
#q41 e1 e2 e2
#q63 e1 e0 e2
您可以cbind
的第一列取回ID
的列。
cbind(df[1], do.call("cbind.data.frame", split(unlist(df[vals]), unlist(df[cols]))))
# ID c1 c2 c3
#q22 1 e1 e1 e0
#q41 2 e1 e2 e2
#q63 3 e1 e0 e2
正如@Farah Nazifa所提到的,如果我们也希望保持每一列的行顺序,我们可以如下使用mapply
。
col_values <- unlist(df[cols])
data.frame(mapply(function(x, y) x[y],
split(unlist(df[vals]), col_values), split(row(df[vals]), col_values)))
# c1 c2 c3
#q41 e1 e1 e2
#q22 e1 e0 e2
#q63 e1 e2 e0
答案 1 :(得分:0)
看起来像是要变长的堆栈,然后将其重塑为宽格式将完成此操作。这种逻辑大约有320万种变体,但这是一种:
tmp <- reshape(dat, idvar="ID", varying=list(c(2,4,6),c(3,5,7)),
v.names=c("name","value"), direction="long", timevar=NULL)
# ID name value
#1.1 1 c2 e1
#2.1 2 c1 e1
#3.1 3 c3 e0
#1.2 1 c1 e1
#2.2 2 c3 e2
#3.2 3 c2 e2
#1.3 1 c3 e2
#2.3 2 c2 e0
#3.3 3 c1 e1
这种长格式甚至可以用于建模目的。如果您确实需要宽幅格式,请重新整形:
reshape(tmp, idvar="ID", timevar="name", direction="wide")
# ID value.c2 value.c1 value.c3
#1.1 1 e1 e1 e2
#2.1 2 e0 e1 e2
#3.1 3 e2 e1 e0
答案 2 :(得分:0)
我们可以使用melt/dcast
中的data.table
library(data.table)
dcast(melt(setDT(df1), measure = patterns('^q[135]', '^q[246]')),
ID ~ value1, value.var = 'value2')
# ID c1 c2 c3
#1: 1 e1 e1 e2
#2: 2 e1 e0 e2
#3: 3 e1 e2 e0
df1 <- structure(list(ID = 1:3, q1 = c("c2", "c1", "c3"), q2 = c("e1",
"e1", "e0"), q3 = c("c1", "c3", "c2"), q4 = c("e1", "e2", "e2"
), q5 = c("c3", "c2", "c1"), q6 = c("e2", "e0", "e1")),
class = "data.frame", row.names = c(NA, -3L))