R,data.table或dplyr,长格式拆分列号

时间:2016-05-03 18:41:14

标签: r reshape

想象一下,我有一个包含列名的数据框,例如Mary1,Mary2,Mary3,Bob1,Bob2,Bob3,Pam1,Pam2,Pam3等,但还有更多列。

让我们举一个简单的可重复的例子。

set.seed(1)
mydata <- data.frame()
mydata <- rbind(mydata,c(1,round(runif(30),3)))
mydata <- rbind(mydata,c(2,round(runif(30),3)))
mydata <- rbind(mydata,c(3,round(runif(30),3)))
colnames(mydata) <- c("id", paste0(rep(LETTERS[1:10], each=3), 1:3))   

给出:

id    A1    A2    A3    B1    B2    B3    C1    C2    C3    D1    D2    D3    E1    E2    E3    F1    F2    F3    G1    G2    G3    H1    H2    H3    I1    I2    I3    J1    J2    J3  ...
1  0.266 0.372 0.573 0.908 0.202 0.898 0.945 0.661 0.629 0.062 0.206 0.177 0.687 0.384 0.770 0.498 0.718  0.992 0.380 0.777 0.935 0.212 0.652 0.126 0.267 0.386 0.013 0.382 0.870 0.340  ...
2  0.482 0.600 0.494 0.186 0.827 0.668 0.794 0.108 0.724 0.411 0.821 0.647 0.783 0.553 0.530 0.789 0.023  0.477 0.732 0.693 0.478 0.861 0.438 0.245 0.071 0.099 0.316 0.519 0.662 0.407  ...
3  0.913 0.294 0.459 0.332 0.651 0.258 0.479 0.766 0.084 0.875 0.339 0.839 0.347 0.334 0.476 0.892 0.864  0.390 0.777 0.961 0.435 0.713 0.400 0.325 0.757 0.203 0.711 0.122 0.245 0.143  ...

我想获得一个长表格格式,如下所示:

set.seed(1)
mydata <- data.frame()
mydata <- rbind(mydata,c(1,1,round(runif(10),3)))
mydata <- rbind(mydata,c(1,2,round(runif(10),3)))
mydata <- rbind(mydata,c(1,3,round(runif(10),3)))
mydata <- rbind(mydata,c(2,1,round(runif(10),3)))
mydata <- rbind(mydata,c(2,2,round(runif(10),3)))
mydata <- rbind(mydata,c(2,3,round(runif(10),3)))
colnames(mydata) <- c("id","N", LETTERS[1:10])

这&#39; S:

 id  N     A     B     C     D     E     F     G     H     I     J
  1  1 0.266 0.372 0.573 0.908 0.202 0.898 0.945 0.661 0.629 0.062
  1  2 0.206 0.177 0.687 0.384 0.770 0.498 0.718 0.992 0.380 0.777
  1  3 0.482 0.600 0.494 0.186 0.827 0.668 0.794 0.108 0.724 0.411
  2  1 0.935 0.212 0.652 0.126 0.267 0.386 0.013 0.382 0.870 0.340
  2  2 0.821 0.647 0.783 0.553 0.530 0.789 0.023 0.477 0.732 0.693
  2  3 0.478 0.861 0.438 0.245 0.071 0.099 0.316 0.519 0.662 0.407

如何使用data.table或dplyr / tidyr获取它?或任何其他简单的选择。

如果我尝试

melt(mydata, id=1)

结果是一列。

我一直在检查官方帮助和小插曲,但我只能找到更简单的示例,只有少量列,用户手动指定每一个,以及一个模式的例子()但我我不能适应我的榜样。

其他主题使用gsub,但这对我来说很困惑。

我真正想做的事情有点复杂,但我认为这是第一步(我后来再次施展)。 想象一下,我的专栏是Mary1,Mary2,Bob1,Bob2,Pam1,Pam2 ...... 我想创建新的列,每两个上面提到的差异:Mary1-Mary2,Bob1-Bob2,Pam1-Pam2 ...

总结:我不想手工编写所有列的名称,但选择它们会自动删除最后一位数。

PD:好的,我升级了我的问题。 它不仅适用于A1,A2等名称,还适用于较长的名称,例如

colnames(mydata) <- c("id", paste0(rep(LETTERS[1:10], each=3), rep(LETTERS[1:10], each=3), 1:3)) 

我不介意速度,我正在寻找简单而不神秘的东西。

3 个答案:

答案 0 :(得分:5)

使用data.table::melt

require(data.table)
n = unique(gsub("[0-9]+$", "", names(mydata)[-1L]))
p = paste0("^", n)

melt(setDT(mydata), measure=patterns(p), value.name=n, variable.name="N")
#    id N     A     B     C     D     E     F     G     H     I     J
# 1:  1 1 0.266 0.908 0.945 0.062 0.687 0.498 0.380 0.212 0.267 0.382
# 2:  2 1 0.482 0.186 0.794 0.411 0.783 0.789 0.732 0.861 0.071 0.519
# 3:  3 1 0.913 0.332 0.479 0.875 0.347 0.892 0.777 0.713 0.757 0.122
# 4:  1 2 0.372 0.202 0.661 0.206 0.384 0.718 0.777 0.652 0.386 0.870
# 5:  2 2 0.600 0.827 0.108 0.821 0.553 0.023 0.693 0.438 0.099 0.662
# 6:  3 2 0.294 0.651 0.766 0.339 0.334 0.864 0.961 0.400 0.203 0.245
# 7:  1 3 0.573 0.898 0.629 0.177 0.770 0.992 0.935 0.126 0.013 0.340
# 8:  2 3 0.494 0.668 0.724 0.647 0.530 0.477 0.478 0.245 0.316 0.407
# 9:  3 3 0.459 0.258 0.084 0.839 0.476 0.390 0.435 0.325 0.711 0.143

答案 1 :(得分:4)

set.seed(1)
mydata <- data.frame()
mydata <- rbind(mydata,c(1,round(runif(30),3)))
mydata <- rbind(mydata,c(2,round(runif(30),3)))
mydata <- rbind(mydata,c(3,round(runif(30),3)))
colnames(mydata) <- c("id", paste0(rep(LETTERS[1:10], each=3), 1:3)) 

reshape(mydata, dir = 'long', varying = names(mydata)[-1], sep = '', timevar = 'N')

#     id N     A     B     C     D     E     F     G     H     I     J
# 1.1  1 1 0.266 0.908 0.945 0.062 0.687 0.498 0.380 0.212 0.267 0.382
# 2.1  2 1 0.482 0.186 0.794 0.411 0.783 0.789 0.732 0.861 0.071 0.519
# 3.1  3 1 0.913 0.332 0.479 0.875 0.347 0.892 0.777 0.713 0.757 0.122
# 1.2  1 2 0.372 0.202 0.661 0.206 0.384 0.718 0.777 0.652 0.386 0.870
# 2.2  2 2 0.600 0.827 0.108 0.821 0.553 0.023 0.693 0.438 0.099 0.662
# 3.2  3 2 0.294 0.651 0.766 0.339 0.334 0.864 0.961 0.400 0.203 0.245
# 1.3  1 3 0.573 0.898 0.629 0.177 0.770 0.992 0.935 0.126 0.013 0.340
# 2.3  2 3 0.494 0.668 0.724 0.647 0.530 0.477 0.478 0.245 0.316 0.407
# 3.3  3 3 0.459 0.258 0.084 0.839 0.476 0.390 0.435 0.325 0.711 0.143

答案 2 :(得分:3)

以下是tidyr的一个解决方案:

library(tidyr)
mydata %>%
  gather(key, value, -id) %>%
  separate(key, into = c('key1', 'key2'),
           sep = '(?<=[a-zA-Z])(?=[0-9])') %>%
  spread(key1, value)

结果输出:

  id key2     A     B     C     D     E     F     G     H     I     J
1  1    1 0.266 0.908 0.945 0.062 0.687 0.498 0.380 0.212 0.267 0.382
2  1    2 0.372 0.202 0.661 0.206 0.384 0.718 0.777 0.652 0.386 0.870
3  1    3 0.573 0.898 0.629 0.177 0.770 0.992 0.935 0.126 0.013 0.340
4  2    1 0.482 0.186 0.794 0.411 0.783 0.789 0.732 0.861 0.071 0.519
5  2    2 0.600 0.827 0.108 0.821 0.553 0.023 0.693 0.438 0.099 0.662
6  2    3 0.494 0.668 0.724 0.647 0.530 0.477 0.478 0.245 0.316 0.407
7  3    1 0.913 0.332 0.479 0.875 0.347 0.892 0.777 0.713 0.757 0.122
8  3    2 0.294 0.651 0.766 0.339 0.334 0.864 0.961 0.400 0.203 0.245
9  3    3 0.459 0.258 0.084 0.839 0.476 0.390 0.435 0.325 0.711 0.143