我只想获取一个包含两列的数据框,一列带有分组变量,第二列带有值,然后对其进行转换,使分组变量成为具有适当值的列。一个非常简单的问题,但搜索了大约一个小时后,我找不到一个好的答案。这是一个玩具示例:
var <- c("Var1", "Var1", "Var2", "Var2")
value <- c(1, 2, 3, 4)
df <- data.frame(var, value)
df.one <- df[df$var == "Var1", ]
df.two <- df[df$var == "Var2", ]
desired.df <- data.frame(df.one[2], df.two[2])
colnames(desired.df) <- c("Var1", "Var2")
desired.df
随着更多的变量和值,这段代码可能变得非常笨重。有谁能建议更好的方法?任何建议将不胜感激!
答案 0 :(得分:5)
数据:
df <- structure(list(var = structure(c(1L, 1L, 2L, 2L),
.Label = c("Var1", "Var2"), class = "factor"),
value = c(1, 2, 3, 4)), .Names = c("var", "value"),
class = "data.frame", row.names = c(NA, -4L))
在var
中引入一个标识观察结果的新变量看起来很有用(我在下面称之为case
);如果你愿意,你可以在重塑它之后将其删除。
使用reshape2
/ plyr
:
library("plyr")
library("reshape2")
## add 'case' identifier
df <- ddply(df,"var",mutate,case=1:length(var))
## dcast() to reshape; then drop identifier
dcast(df,case~var)[,-1]
使用tidyr
(相同策略):
library("tidyr")
library("dplyr")
df %>% group_by(var) %>%
mutate(case=seq(n())) %>%
spread(var,value) %>%
select(-case)
这可能也可以用基础R中的reshape()
完成,但我从来没有弄明白......
答案 1 :(得分:4)
Base R解决方案:
data.frame(split(df$value,df$var))
# Var1 Var2
#1 1 3
#2 2 4
这个解决方案意味着所有的“Varn”&#39;子集的长度相等。 更一般的解决方案是:
z <- split(df$value,df$var)
max.length <- max(sapply(z,length))
data.frame(lapply(z,`length<-`,max.length))
将NA附加到较短的列表,以确保所有列表具有相同的长度。