如何使用reshape包重新整形此数据帧

时间:2012-01-13 15:57:25

标签: r reshape

我有一个非常大的数据框,结构如下:

id    x1    x2    x3    y1    y2    y3    z1    z2    z3     v 
 1     2     4     5    10    20    15   200   150   170   2.5
 2     3     7     6    25    35    40   300   350   400   4.2

我需要创建一个这样的数据框:

id   xsource   xvalue   yvalue   zvalue       v 
 1        x1        2       10      200     2.5
 1        x2        4       20      150     2.5
 1        x3        5       15      170     2.5
 2        x1        3       25      300     4.2
 2        x2        7       35      350     4.2
 2        x3        6       40      400     4.2

我很确定我必须使用重塑包来做,但我无法得到我想要的东西。

你能帮帮我吗?

谢谢

5 个答案:

答案 0 :(得分:8)

这是reshape()解决方案。

关键位是varying=参数可以采用宽格式的列名称向量列表,这些列号对应于长格式的单个变量。在这种情况下,原始数据框中的列"x1", "x2", "x3"将发送到长数据框中的一列,列"y1, y2, y3"将进入第二列,依此类推。

# Read in the original data, x, from Andrie's answer

res <- reshape(x, direction = "long", idvar = "id",
               varying = list(c("x1","x2", "x3"), 
                              c("y1", "y2", "y3"), 
                              c("z1", "z2", "z3")),
               v.names = c("xvalue", "yvalue", "zvalue"), 
               timevar = "xsource", times = c("x1", "x2", "x3"))
#      id   v xsource xvalue yvalue zvalue
# 1.x1  1 2.5      x1      2     10    200
# 2.x1  2 4.2      x1      3     25    300
# 1.x2  1 2.5      x2      4     20    150
# 2.x2  2 4.2      x2      7     35    350
# 1.x3  1 2.5      x3      5     15    170
# 2.x3  2 4.2      x3      6     40    400

最后,需要一些纯粹的化妆步骤才能使结果看起来完全,如您的问题所示:

res <- res[order(res$id, res$xsource), c(1,3,4,5,6,2)]
row.names(res) <- NULL
res
#   id xsource xvalue yvalue zvalue   v
# 1  1      x1      2     10    200 2.5
# 2  1      x2      4     20    150 2.5
# 3  1      x3      5     15    170 2.5
# 4  2      x1      3     25    300 4.2
# 5  2      x2      7     35    350 4.2
# 6  2      x3      6     40    400 4.2

答案 1 :(得分:2)

以下是使用reshape2的一种方法,我在tidy data的论文中有详细介绍。

第1步:确定已在列中的变量。在这种情况下:id和v。这些是我们融合的变量

library(reshape2)
xm <- melt(x, c("id", "v"))

步骤2:拆分当前合并在一列中的变量。在这种情况下,源(字符部分)和rep(整数部分):

有很多方法可以做到这一点,我将使用stringr

来使用字符串提取
library(stringr)
xm$source <- str_sub(xm$variable, 1, 1)
xm$rep <- str_sub(xm$variable, 2, 2)
xm$variable <- NULL

步骤3:重新排列当前行中但我们想要列的变量:

dcast(xm, ... ~ source)

#   id   v rep x  y   z
# 1  1 2.5     1 2 10 200
# 2  1 2.5     2 4 20 150
# 3  1 2.5     3 5 15 170
# 4  2 4.2     1 3 25 300
# 5  2 4.2     2 7 35 350
# 6  2 4.2     3 6 40 400

答案 2 :(得分:1)

有人请证明我错了,但我认为使用reshape包或基本reshape函数解决此问题并不容易。

但是,使用lapplydo.call

很容易

复制数据:

x <- read.table(text="
id    x1    x2    x3    y1    y2    y3    z1    z2    z3     v 
1     2     4     5    10    20    15   200   150   170   2.5
2     3     7     6    25    35    40   300   350   400   4.2
", header=TRUE)

进行分析

chunks <- lapply(1:nrow(x), 
    function(i)cbind(x[i, 1], 1:3, matrix(x[i, 2:10], ncol=3), x[i, 11]))
res <- do.call(rbind, chunks)
colnames(res) <- c("id", "source", "x", "y", "z", "v")
res

     id source x y  z   v  
[1,] 1  1      2 10 200 2.5
[2,] 1  2      4 20 150 2.5
[3,] 1  3      5 15 170 2.5
[4,] 2  1      3 25 300 4.2
[5,] 2  2      7 35 350 4.2
[6,] 2  3      6 40 400 4.2

答案 3 :(得分:0)

尝试使用reshapeGUI包。它使用了plyr包和reshape2包,它为您提供了一个易于使用的界面,允许您在执行之前预览您的重塑。它还为您提供了重塑的代码,因此您可以将其粘贴到脚本中以实现可重现性,这样您就可以学习在reshape2中使用融合和强制转换命令。对于那些没有重塑ninjas的人来说,这是一个很好的复杂数据操作方法。

答案 4 :(得分:0)

以下是阅读此问题的人可能会感兴趣的两种最新方法:

选项1:tidyverse

library(tidyverse)
x %>% 
  gather(var, val, -id, -v) %>% 
  extract(var, into = c("header", "source"), regex = "([a-z])([0-9])") %>% 
  spread(header, val)
#   id   v source x  y   z
# 1  1 2.5      1 2 10 200
# 2  1 2.5      2 4 20 150
# 3  1 2.5      3 5 15 170
# 4  2 4.2      1 3 25 300
# 5  2 4.2      2 7 35 350
# 6  2 4.2      3 6 40 400

选项2:data.table

library(data.table)
setDT(x)
melt(x, measure.vars = patterns("x", "y", "z"), 
     value.name = c("x", "y", "z"), 
     variable.name = "source")
#    id   v source x  y   z
# 1:  1 2.5      1 2 10 200
# 2:  2 4.2      1 3 25 300
# 3:  1 2.5      2 4 20 150
# 4:  2 4.2      2 7 35 350
# 5:  1 2.5      3 5 15 170
# 6:  2 4.2      3 6 40 400