我的数据结构如下所示:
groupA1 groupA2 groupB1 groupB2 date text
0 1 1 1 2013-01-01 the dog
对于每个groupB
变量,我想为每列值为1的列列出一行。
我需要列出groupA
和groupB
的所有组合,其中1s存在于一行中,但随后还将日期和文本添加到每个组合中作为该行中的列。
转化后的数据显示为:
var_groupB var_groupA date text
groupB1 groupA2 2013-01-01 the dog
groupB2 groupA2 2013-01-01 the dog
我尝试过melt
和ddply
的组合,但总是没有我需要的变量之一。
我试过的一件事是melt(x, id.vars=c("text", "date"))
,但后来我丢失了groupA
和groupB
之间关系的所有信息。
我可以使用凌乱的循环完成此操作,但不确定是否存在我不知道并且可以完成工作的reshape
实用程序。
答案 0 :(得分:5)
你可以melt
两次,每组一次:
y <- melt(x, measure.vars=c("groupA1", "groupA2"),
variable.name="var_groupA", value.name="val_groupA")
y <- melt(y, measure.vars=c("groupB1", "groupB2"),
variable.name="var_groupB", value.name="val_groupB")
对于A和B的每个组合,这将给你一行:
date text var_groupA val_groupA var_groupB val_groupB
1 2013-01-01 the dog groupA1 0 groupB1 1
2 2013-01-01 the dog groupA2 1 groupB1 1
3 2013-01-01 the dog groupA1 0 groupB2 1
4 2013-01-01 the dog groupA2 1 groupB2 1
然后您可以对此进行子集化并删除值列:
y <- y[y$val_groupA == 1 & y$val_groupB==1, ]
y <- y[, c("var_groupA", "var_groupB", "date", "text")]
它可以为您提供所需内容:
var_groupA var_groupB date text
2 groupA2 groupB1 2013-01-01 the dog
4 groupA2 groupB2 2013-01-01 the dog
当然,如果您的数据集比您的示例更复杂,您可以通过以更自动化的方式进行融合和子集化来使此解决方案更加优雅 - 例如,检测组列并填充{{1} },measure.vars
和variable.name
会自动生成,也许适用于任意数量的群组。
答案 1 :(得分:2)
前两个语句将前4列中的每个0替换为“”,每个1中的列名称替换为dd2
。接下来的两个语句使用groupA
为每行生成groupB
和expand.grid
的所有组合,结果为dd3
。最后subset
到那些没有""
条目的行:
newvals <- function(nm) ifelse(dd[[nm]] == 0, "", nm)
dd2 <- replace(dd, 1:4, lapply(names(dd)[1:4], newvals))
combo <- function(x) data.frame(expand.grid(groupA=c(x[1:2]), groupB=c(x[3:4])),
x$date, x$text)
dd3 <- do.call("rbind", by(dd2, 1:nrow(dd2), combo))
subset(dd3, groupA != "" & groupB != "")
这给出了:
groupA groupB x.date x.text
1.2 groupA2 groupB1 2013-01-01 the dog
1.4 groupA2 groupB2 2013-01-01 the dog