如何在R中将一行拆分为3行?

3

So I have a table in R like this:

id    col1    col2    col3    col4    col5     col6     col7     col8   col9 
101   1       1111    202     2       1120     5512     3        1221   900
102   1       2999    1110    2       2000     5000     3        80     200
103   1       1121    333     2       111      222      3        101    1000
. 
.

我正在尝试将每个科目的长行转换为多行,就像这样:

id   trial   col1   col2   
101  1       1111   202
101  2       1120   5512
101  3       1221   900
102  1       2999   1110
102  2       2000   5000
102  3       80     200
103  1       1121   333
103  2       111    222
103  3       101    1000

我是一名R语言新手,希望能得到帮助。我想将col作为三元组读取并编译它们,但不知道该如何操作。


请在您选择的软件包中查看 melt。同时重命名 col{1,4,7} 也会有所帮助。 - MichaelChirico
tidyr是另一个很好的处理数据的包。 - Jacob H
@michaelchirico 看起来使用melt可能是一个好的选择,但在这种情况下你会如何使用它,特别是因为我将折叠多个列。 - Ken Lam
请参阅data.table包中的melt函数,该函数接受多个measure.vars参数。 - MichaelChirico
4个回答

3
你的数据存在一个问题,它以一种非常不传统的方式存储。通常当数据从宽格式转换为长格式时,在宽数据中的变量名称将成为长数据中的数据点,因此称为“数据透视表”。为了解决这个问题,我建议你按照以下方式转换数据:
d <- d[, !grepl("col[147]", names(d))] 

names(d)[-1] <- paste(sort(rep(1:3, 2)), paste0("col", 1:2))

一旦你完成了这一步骤,使用 tidyr 包来重塑数据就相对简单了。

d %>%
  gather(key, value, -id) %>%
  separate(key, c("trial", "new"), sep = "\\s") %>%
  spread(new, value)

这个运行得非常好。如果你想更进一步自动化进程怎么办?比如说,如果试验编号不是按顺序排列的,或者它是随机字符串。 - Ken Lam
@KenLam 你可以通过以下方法获取试验编号。如果你知道哪些列包含试验编号,则 unique(d[, grepl("col[147]", names(d))]) 将为你提供试验编号。如果你不知道哪些列包含试验编号,则需要先找到它们。为此,你需要了解一些关于试验编号的信息。例如,可能情况是试验编号是一个数字,并且所有其他数据不是单个数字,那么你可以使用类似这样的代码 grep("^[0-9]$", d[2,], value=TRUE) 找到试验编号。 - Jacob H

2
(有点繁琐)这个如何处理?
res <- cbind(rep(df[,1], each = nrow(df)), matrix(c(t(df[-1])), ncol = 3, byrow = TRUE))
colnames(res) <- c("id", "trial", "col1", "col2")
res
       id trial col1 col2
 [1,] 101     1 1111  202
 [2,] 101     2 1120 5512
 [3,] 101     3 1221  900
 [4,] 102     1 2999 1110
 [5,] 102     2 2000 5000
 [6,] 102     3   80  200
 [7,] 103     1 1121  333
 [8,] 103     2  111  222
 [9,] 103     3  101 1000

2

这里有另一种使用array的选项。

cbind(rep(df1$id, 
  each=nrow(df1)),apply(aperm(array(unlist(df1[-1]), 
           dim=c(3,3,3)), c(3,2,1)), 2, c))
#      [,1] [,2] [,3] [,4]
# [1,]  101    1 1111  202
# [2,]  101    2 1120 5512
# [3,]  101    3 1221  900
# [4,]  102    1 2999 1110
# [5,]  102    2 2000 5000
# [6,]  102    3   80  200
# [7,]  103    1 1121  333
# [8,]  103    2  111  222
# [9,]  103    3  101 1000

数据

df1 <- structure(list(id = 101:103, col1 = c(1L, 1L, 1L), 
 col2 = c(1111L, 
 2999L, 1121L), col3 = c(202L, 1110L, 333L), col4 = c(2L, 2L, 
2L), col5 = c(1120L, 2000L, 111L), col6 = c(5512L, 5000L, 222L
 ), col7 = c(3L, 3L, 3L), col8 = c(1221L, 80L, 101L), 
col9 = c(900L, 
200L, 1000L)), .Names = c("id", "col1", "col2", "col3", 
"col4", 
"col5", "col6", "col7", "col8", "col9"), class = "data.frame", 
 row.names = c(NA, -3L))

1
text1 = "
id    col1    col2    col3    col4    col5     col6     col7     col8   col9 
101   1       1111    202     2       1120     5512     3        1221   900
102   1       2999    1110    2       2000     5000     3        80     200
103   1       1121    333     2       111      222      3        101    1000
"

df1 <- read.table(text=text1, head=T, as.is=T)

library(plyr)

ddply(df1, .(id), function(df){
  df1 <- df[, 2:4]
  df2 <- df[, 5:7]
  df3 <- df[, 8:10]
  names(df1) <- c("trial", "col1", "col2")
  names(df2) <- c("trial", "col1", "col2")
  names(df3) <- c("trial", "col1", "col2")
  df.n <- do.call(rbind, list(df1, df2, df3))
  return(df.n)
})
#    id trial col1 col2
# 1 101     1 1111  202
# 2 101     2 1120 5512
# 3 101     3 1221  900
# 4 102     1 2999 1110
# 5 102     2 2000 5000
# 6 102     3   80  200
# 7 103     1 1121  333
# 8 103     2  111  222
# 9 103     3  101 1000

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接