我有一个非常大的数据框,结构如下:
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
我很确定我必须使用重塑包来做,但我无法得到我想要的东西。
你能帮帮我吗?
谢谢
答案 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
函数解决此问题并不容易。
但是,使用lapply
和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
答案 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