我不知道使用dcast()
是否正确,但我想重塑以下data.frame:
df <- data.frame(x=c("p1","p1","p2"),y=c("a","b","a"),z=c(14,14,16))
df
x y z
1 p1 a 14
2 p1 b 14
3 p2 a 16
所以它看起来像这样:
df2 <- data.frame(x=c("p1","p2"),a=c(1,1),b=c(1,0),z=c(14,16))
x a b z
1 p1 1 1 14
2 p2 1 0 16
y
中的变量df
应该被打破,以便其元素是新变量,每个虚拟编码。所有其他变量(在这种情况下只是z
)对于每个人(p1,p2等)都是相等的。特定人员p具有不同值的唯一变量是y
我想要这个的原因是因为我需要通过变量x
将此数据集与其他数据集合并。事实是,每人需要一排(p1,p2等)。
答案 0 :(得分:2)
以下作品,但似乎很麻烦。
df2 <- df
df2$y <- as.numeric(y)
df$y2 <- as.numeric(df$y)
df2 <- dcast(df, x+z~y, value.var="y2")
df2
x z a b
1 p1 14 1 2
2 p2 16 1 NA
答案 1 :(得分:2)
这几乎是previous question的重复,我在那里使用的基本答案也是如此。也不需要任何外部包。
aggregate(model.matrix(~ y - 1, data=df),df[c("x","z")],max)
x z ya yb
1 p1 14 1 1
2 p2 16 1 0
要解释这一点,因为它有点奇怪,最基本的model.matrix
调用会为data.frame的每一行的每个唯一值返回一个二进制指示符变量,如下所示:
ya yb
1 1 0
2 0 1
3 1 0
如果aggregate
您的两个id变量(x
和z
)的中间结果,那么您基本上是在初始data.frame上执行:
x z ya yb
1 p1 14 1 0
2 p1 14 0 1
3 p2 16 1 0
因此,如果您在max
和ya
的每个组合中使用yb
值x
和z
,那么您基本上可以这样做:
x z ya yb
1 p1 14 1*max* 0
2 p1 14 0 1*max*
--collapse--
x z ya yb
1 p1 14 1 1
...并对每个唯一的x
/ z
组合重复一遍,以得出最终结果:
x z ya yb
1 p1 14 1 1
2 p2 16 1 0
将这一点推广到更多列时,事情变得有点疯狂,但它可以通过this question提供,例如:
df <- data.frame(x=c("p1","p1","p2"),y=c("a","b","a"),z=c("14","15","16"))
intm <- model.matrix(~ y + z - 1, data=df,
contrasts.arg = sapply(df[2:3], contrasts, contrasts=FALSE))
aggregate(intm,df[c("x")],max)
x ya yb z14 z15 z16
1 p1 1 1 1 1 0
2 p2 1 0 0 0 1
答案 2 :(得分:1)
我不太清楚你必须这么做但是如果你需要一种方法来自动化它,我写了这个可能有帮助的小功能:
首先运行dcast:
new = dcast(df, x+z~y, value.var="y")
加载到R环境中:
# args to be passed:
# df is your dataframe
# cols is a list of format c("colname1", "colname2", ... , "colnameN")
binarizeCols = function(df, cols){
for(i in cols){
column = which(colnames(df) == i)
truthRow = is.na(df[,column])
for(j in 1:length(truthRow)){
if(truthRow[j] == FALSE){
df[j,column] = 1
}else{
df[j,column] = 0
}
}
}
return(df)
}
然后运行:
new = binarizeCols(new, c("a", "b"))
你得到:
x z a b
1 p1 14 1 1
2 p2 16 1 0
没有使用_apply()快但没有硬编码,你可以输入你想要的任何名字(也许你想跳过中间的一个?)而你不会创建你的df的新实例。 注意:我使用“=”而不是“&lt; - ”,因为我认为它正在逐步淘汰,但如果需要可以替换它们。
答案 3 :(得分:0)
df <- data.frame(x=c("p1","p1","p2","p3"),
y=c("a","b","a","c"),
z=c(14,14,16,17)) # wanted larger test case.
new <- dcast(df, x+z~y, value.var="y")
new[3:5] <- sapply(lapply(new[3:5], '%in%', unique(df$y) ), as.numeric)
new
x z a b c
1 p1 14 1 1 0
2 p2 16 1 0 0
3 p3 17 0 0 1
首先检查向量中的包含,该向量总结了创建逻辑值列的可能值。然后通过取这些逻辑值的as.numeric来'dummify'。