【问题标题】:How to do a simple transpose/pivot in R如何在 R 中进行简单的转置/旋转
【发布时间】:2015-02-11 20:28:20
【问题描述】:

我只想获取一个包含两列的数据框,一列带有分组变量,第二列带有值,然后对其进行转换,以便分组变量成为具有适当值的列。一个非常简单的问题,但是搜索了大约一个小时后,我找不到一个好的答案。这是一个玩具示例:

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

随着变量和值的增加,这段代码可能会变得非常笨重。任何人都可以提出更好的方法吗?任何建议将不胜感激!

【问题讨论】:

  • 使用dcast 包中的reshape2

标签: r reshape


【解决方案1】:

数据:

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() 来完成,但我一直无法弄清楚...

【讨论】:

    【解决方案2】:

    基础 R 解决方案:

    data.frame(split(df$value,df$var))
    #  Var1 Var2
    #1    1    3
    #2    2    4
    

    此解决方案意味着所有“VarN”子集的长度相同。 更通用的解决方案是:

    z <- split(df$value,df$var)
    max.length <- max(sapply(z,length))
    data.frame(lapply(z,`length<-`,max.length))
    

    将 NA 附加到较短的列表以确保所有列表具有相同的长度。

    【讨论】:

    • 这当然只在“Var1”和“Var2”数量相等时才有效。更一般地(并且可怕地)这可以在reshape(cbind(df,count=ave(rep(1,nrow(df)),df$var,FUN=cumsum)),idvar="count",timevar="var",direction="wide")[,-1] 的基础上完成
    • @A.Webb,您的解决方案在 df &lt;- structure(list(var = structure(c(1L, 1L, 2L, 3L), .Label = c("Var1", "Var2", "Var3"), class = "factor"), value = c(1, 2, 3, 4), case = c(1L, 2L, 1L, 1L)), .Names = c("var", "value", "case"), row.names = c(NA, -4L), class = "data.frame") 的情况下添加了一些额外的输出
    • 强制长度更大以进行 NA-padding 让我觉得太聪明了。我宁愿写一个简短的 NA-padding 函数(或者从某处的包中获取一个:pad.na(x,n) &lt;- c(x,rep(NA,length.out=max(0,n-length(x)))
    • @BenBolker,这是一个官方记录的功能:?length 说“当一个向量被加长时,它会用 NAs 填充到它的新长度(原始向量为 nul)。” :)
    • 我知道这是官方记录的行为。这对我的口味来说太聪明了。这就像使用x+0 将逻辑转换为数字一样。
    猜你喜欢
    • 1970-01-01
    • 2019-07-11
    • 1970-01-01
    • 2012-09-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-24
    • 1970-01-01
    相关资源
    最近更新 更多