2

我不知道我是否通过标题解释了我的意图,但本质上我想转换

        mean    sd
v1  -32.72  0.565
v2  -50.47  1.543
v3  -30.17  0.9295
v4  -38.56  0.4541
g1  5.649   0.02509
g2  1.672   0.02992
g3  3.139   0.03507
g4  7.169   0.06703
y1  271.1   3.48
y2  123.7   1.81
y3  138.9   2.727
y4  405.5   4.396

 v.mean v.sd    g.mean  g.sd    y.mean  y.sd
-32.72  0.565   5.649   0.02509 271.1   3.48
-50.47  1.543   1.672   0.02992 123.7   1.81
-30.17  0.9295  3.139   0.03507 138.9   2.727
-38.56  0.4541  7.169   0.06703 405.5   4.396

我想这样做而不使用 for 循环。我觉得有一些reshape功能可以做到这一点。我有大量具有这种配置的数据集。所以,我想要一些矢量化解决方案......而且,长度可以是任何东西。这里,在示例数据中,序列长度为 4。另外,我对列名并不挑剔。我可以使用names(dataframe)=c(....

4

3 回答 3

5

确实有一个名为 的函数reshape。假设您的 data.frame 被命名为“数据”,请执行以下操作以获得您想要的结果:

data$group <- substr(rownames(data),1,1)
data$id <- substr(rownames(data),2,2)
result <- reshape(data, v.names=c("mean","sd"), idvar="id", timevar="group", direction="wide")

有关详细信息,请参阅?reshape

于 2013-01-03T22:26:05.933 回答
1

使用reshap2,我们应用acast在一个巧妙的融合数据中。

dat <- read.table(text ='v1  -32.72  0.565
v2  -50.47  1.543
v3  -30.17  0.9295
v4  -38.56  0.4541
g1  5.649   0.02509
g2  1.672   0.02992
g3  3.139   0.03507
g4  7.169   0.06703
y1  271.1   3.48
y2  123.7   1.81
y3  138.9   2.727
y4  405.5   4.396')
colnames(dat) <- c('var','mean','sd')

首先我融化我的数据:

dat.m <- melt(dat)
Using var as id variables
   var variable     value
1   v1     mean -32.72000
2   v2     mean -50.47000
3   v3     mean -30.17000
4   v4     mean -38.56000
5   g1     mean   5.64900

现在我想我需要拆分 var 列,以便在以后的列中只使用 var 的字母。通常我们使用 ColSplit但这里没有可见的模式,所以我手动创建列并应用acast

dat.m$vv <- substr(dat.m$var,1,1)
dat.m$key <- substr(dat.m$var,2,2)
acast(dat.m[,-1],id ~variable+vv)
  mean_g mean_v mean_y    sd_g   sd_v  sd_y
1  5.649 -32.72  271.1 0.02509 0.5650 3.480
2  1.672 -50.47  123.7 0.02992 1.5430 1.810
3  3.139 -30.17  138.9 0.03507 0.9295 2.727
4  7.169 -38.56  405.5 0.06703 0.4541 4.396
于 2013-01-03T22:45:33.923 回答
1

这是与@Theodore 的答案非常相似的方法。假设您的数据集称为“dat”:

reshape(cbind(dat, do.call(rbind, strsplit(rownames(dat), ""))), 
        idvar="2", timevar="1", direction = "wide")
#    2 mean.v   sd.v mean.g    sd.g mean.y  sd.y
# v1 1 -32.72 0.5650  5.649 0.02509  271.1 3.480
# v2 2 -50.47 1.5430  1.672 0.02992  123.7 1.810
# v3 3 -30.17 0.9295  3.139 0.03507  138.9 2.727
# v4 4 -38.56 0.4541  7.169 0.06703  405.5 4.396

在上面:

  • do.call(rbind, strsplit(rownames(dat), ""))创建一个两列矩阵,其中第一列是字母“v”、“g”和“y”,第二列是数字 1 到 4。这一步可能过于简化了类似的问题,因为它只适用于双字符rownames;对于更复杂的场景,您可能不得不求助于一些正则表达式。
  • cbind(...)将此新矩阵与您的原始矩阵集成data.frame;新的列名只是“1”和“2”。
  • 您的“时间”变量是包含字母“v”、“g”和“y”的新列(名为“2”的列);您的“id”变量是包含数字 1 到 4 的新列(名为“1”的列)。将该信息用于reshape()您的数据。

reshape()将数据获取到该阶段后,使用该功能的另一种方法是使用aggregate()

aggregate(cbind(mean, sd) ~ `2`, 
          data = cbind(dat, do.call(rbind, strsplit(rownames(dat), ""))), 
          FUN = I)
  2  mean.1  mean.2  mean.3    sd.1    sd.2    sd.3
1 1 -32.720   5.649 271.100 0.56500 0.02509 3.48000
2 2 -50.470   1.672 123.700 1.54300 0.02992 1.81000
3 3 -30.170   3.139 138.900 0.92950 0.03507 2.72700
4 4 -38.560   7.169 405.500 0.45410 0.06703 4.39600
于 2013-01-06T17:15:37.137 回答