8

我有一个相当大的数据框,结构如下:

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

我很确定我必须用 reshape 包来做,但我无法得到我想要的。

你可以帮帮我吗?

谢谢

4

5 回答 5

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
于 2012-01-13T18:17:59.193 回答
2

这是一种使用方法,并在我关于tidy datareshape2的论文中进行了深入描述。

第 1 步:识别列中已经存在的变量。在这种情况下:id 和 v。这些是我们融化的变量

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

第 2 步:拆分当前组合在一列中的变量。在这种情况下,这是 source (字符部分)和 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
于 2012-01-14T13:13:23.873 回答
1

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

lapply但是,使用and很容易do.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
于 2012-01-13T16:40:00.467 回答
0

尝试使用 reshapeGUI 包。它利用 plyr 包和 reshape2 包,它为您提供了一个易于使用的界面,允许您在执行之前预览您的 reshape。它还为您提供了您正在执行的重塑的代码,因此您可以将其粘贴到您的脚本中以获得可重复性,这样您就可以学习在 reshape2 中使用熔化和铸造命令。对于那些不是重塑忍者的人来说,这是一个很好的复杂数据操作的拐杖。

于 2012-07-12T14:13:02.613 回答
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
于 2017-12-14T09:08:04.703 回答