重塑数据框中的列

时间:2015-12-21 17:08:29

标签: r reshape

说我有以下数据框:

ID<-c(1,1,1,1,1,2,2,2,2,2,3,3,3,3,3, 4,4,4,4,4,5,5,5,5,5)
Score<- sample(1:20, 25, replace=TRUE)
days<-rep(c("Mon", "Tue", "Wed", "Thu", "Fri"), times=5)
t<-cbind(ID, Score, days)

我想重塑它,以便新列是ID和实际的工作日名称(意思是6列),并且分数值根据其ID和日期名称分配。像这样:

我发现重塑包可能会这样做。试过(融化和演员),但它没有产生我想要的结果,但是在这篇文章中有类似的内容:Melt data for one column

6 个答案:

答案 0 :(得分:9)

使用内置reshape命令的基本R解决方案。

set.seed(12345)
t <- data.frame(id = c(1,1,1,1,1,2,2,2,2,2,3,3,3,3,3,4,4,4,4,4,5,5,5,5,5),
                score = sample(x = 1:20,size = 25,replace = TRUE),
                days = rep(x = c("Mon","Tue","Wed","Thu","Fri"),times = 5))

t.wide <- reshape(data = t,
                  v.names = "score",
                  timevar = "days",
                  idvar = "id",
                  direction = "wide")
names(t.wide) <- gsub(pattern = "score.",replacement = "",x = names(t.wide),fixed = TRUE)
t.wide
   id Mon Tue Wed Thu Fri
1   1  15  18  16  18  10
6   2   4   7  11  15  20
11  3   1   4  15   1   8
16  4  10   8   9   4  20
21  5  10   7  20  15  13

答案 1 :(得分:8)

您可以使用reshape2执行此操作,但需要data.frame才能执行此操作。使用cbind生成一个矩阵。 (并且在这种情况下将所有数值变量转换为字符,因为矩阵只能包含一种数据类型)。

我已经更改了代码以生成一个数据帧,该数据帧已经是长格式(每次观察一行)。

set.seed(123)
ID<-c(1,1,1,1,1,2,2,2,2,2,3,3,3,3,3, 4,4,4,4,4,5,5,5,5,5)
Score<- sample(1:20, 25, replace=TRUE)
days<-rep(c("Mon", "Tue", "Wed", "Thu", "Fri"), times=5)
dat<-data.frame(ID, Score, days)

使用reshape2将其更改为广泛非常简单:

library(reshape2)

res <- dcast(ID~days,value.var="Score",data=dat)


> res
  ID Fri Mon Thu Tue Wed
1  1  16   3   2  12   6
2  2  19  13  12   7  19
3  3  19  19  17   8  15
4  4  15   3   8   1  20
5  5   3  11  18   8  15

答案 2 :(得分:3)

如果您的数据已完成(每个ID的天数相同),您也可以使用unstack

以下是一个例子(使用TARehman答案中的数据):

unstack(t, score ~ days)
#   Fri Mon Thu Tue Wed
# 1  10  15  18  18  16
# 2  20   4  15   7  11
# 3   8   1   1   4  15
# 4  20  10   4   8   9
# 5  13  10  15   7  20

这里是清理列排序,以及添加ID列:

cbind(ID = unique(t$id), unstack(t, score ~ days)[c("Mon", "Tue", "Wed", "Thu", "Fri")])
##   ID Mon Tue Wed Thu Fri
## 1  1  15  18  16  18  10
## 2  2   4   7  11  15  20
## 3  3   1   4  15   1   8
## 4  4  10   8   9   4  20
## 5  5  10   7  20  15  13

答案 3 :(得分:2)

而不是重塑我移动到更新的tidyr包并且也像这样使用dplyr:

library(dplyr)
library(tidyr)

tdf<-as.data.frame(t) %>%
  mutate(Score=as.numeric(Score)) %>%
  spread(days,Score, fill=NA)

glimpse(tdf)

HTH

答案 4 :(得分:2)

使用splitstackshape

的另一个选项
library(splitstackshape)
data = data.frame(t)
out = setnames(cSplit(setDT(data)[, .(x = toString(Score)), by = ID], 
               'x', ','), c('ID', unique(days)))

#> out
#   ID Mon Tue Wed Thu Fri
#1:  1   8  14  11   5  10
#2:  2  16   1   4  14   8
#3:  3   8  18  19  13   3
#4:  4  16   9  19  16   6
#5:  5   7   2   1   2  13

答案 5 :(得分:1)

在dplyr和amp; tidyr包,使用传播来实现以下目的:

library(dplyr)
library(tidyr)
t <- tbl_df(as.data.frame(t))
t %>% spread(days, Score, ID)

您将获得以下输出:

      ID    Fri    Mon    Thu    Tue    Wed
  (fctr) (fctr) (fctr) (fctr) (fctr) (fctr)
1      1     10     10     18     17     10
2      2     18     11     14      3     16
3      3     11     13      9     15     17
4      4     13     13     16     17     11
5      5      7     14      9     15     20