题
我有一个数据结构,如下所示:
groupA1 groupA2 groupB1 groupB2 date text
0 1 1 1 2013-01-01 the dog
对于每个 groupB
变量,我想为每个值为1的列列出一行。我需要列出所有的组合 groupA
和 groupB
其中1出现在一行中,但随后也将日期和文本添加到该行中的每个组合中作为列。
转换后的数据将显示为:
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
实用程序存在,我不知道,可以做的工作。
解决方案
你可以 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
当然,如果您的数据集比您的示例中更复杂,则可以通过以更自动化的方式进行熔化和子集化来使此解决方案更加优雅-例如,检测组列并填写 measure.vars
, variable.name
, ,而 value.name
自动地,也许对于任何数量的组。
其他提示
前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
不隶属于 StackOverflow