r语言 - 每n列将宽重塑为长

  • 本文关键字:r语言 r dplyr transpose
  • 更新时间 :
  • 英文 :


假设我有一个数据帧:

dw <- read.table(header=T, text='
ID     q1    q2   q3     q4     q5    ...q10  
A   10    6     50     10      bA   
B   12    5     70     11      bB
C   20    7     20     8       bC
D   22    8     22     9       bD
')

我想将'ID'之后的每2列移动到新行,所以它看起来像:

ID  q1   q2 
A   10    6     
B   12    5     
C   20    7     
D   22    8 
A   50    10
B   70   11
C   20   8
D   22   9
....

pivot_longer似乎移动每一列而不是多列?

似乎您不关心列名(ID除外),并且它们都是相同的类。为此,我们可以"pivot"。手动,也许没有pivot_lower的保护或权力,但也没有要求。

第一步是确保class不会成为一个问题;因为里面有一些字符串,我们需要将它们全部转换为character:

dw[-1] <- lapply(dw[-1], as.character)

之后,我们可以手动提取每两个(非ID)列,并与ID合并:

cols <- seq_along(dw)[-1]
list_of_frames <- lapply(split(cols, cols %/% 2), function(ind) setNames(dw[,c(1, ind)], c("ID", "q1", "q2")))
list_of_frames
# $`1`
#   ID q1 q2
# 1  A 10  6
# 2  B 12  5
# 3  C 20  7
# 4  D 22  8
# $`2`
#   ID q1 q2
# 1  A 50 10
# 2  B 70 11
# 3  C 20  8
# 4  D 22  9
# $`3`
#   ID q1 q2
# 1  A bA zA
# 2  B bB zB
# 3  C bC zC
# 4  D bD zD

这可以很容易地与几种方法结合使用,选择其中一种:

data.table::rbindlist(list_of_frames)
dplyr::bind_rows(list_of_frames)
do.call(rbind, list_of_frames)
#    ID q1 q2
# 1   A 10  6
# 2   B 12  5
# 3   C 20  7
# 4   D 22  8
# 5   A 50 10
# 6   B 70 11
# 7   C 20  8
# 8   D 22  9
# 9   A bA zA
# 10  B bB zB
# 11  C bC zC
# 12  D bD zD

数据
dw <- structure(list(ID = c("A", "B", "C", "D"), q1 = c("10", "12", "20", "22"), q2 = c("6", "5", "7", "8"), q3 = c("50", "70", "20", "22"), q4 = c("10", "11", "8", "9"), q5 = c("bA", "bB", "bC", "bD"), q6 = c("zA", "zB", "zC", "zD")), row.names = c(NA, -4L), class = "data.frame")

另一个选项:

data.frame(ID = dw$ID,
q1 = unlist(dw[,seq(2, ncol(dw), 2)], use.names = FALSE),
q2 = unlist(dw[,seq(3, ncol(dw), 2)], use.names = FALSE))

与数据:

dw <- structure(list(ID = c("A", "B", "C", "D"),
q1 = c(10L, 12L, 20L, 22L),
q2 = c(6L, 5L, 7L, 8L),
q3 = c(50L, 70L, 20L, 22L),
q4 = c(10L, 11L, 8L, 9L),
q5 = c("bA", "bB", "bC", "bD"),
q6 = c("cc", "dd", "ee", "ff"))
, class = "data.frame", row.names = c(NA, -4L))
data.frame(ID = dw$ID,
q1 = unlist(dw[,seq(2, ncol(dw), 2)], use.names = FALSE),
q2 = unlist(dw[,seq(3, ncol(dw), 2)], use.names = FALSE))
#>    ID q1 q2
#> 1   A 10  6
#> 2   B 12  5
#> 3   C 20  7
#> 4   D 22  8
#> 5   A 50 10
#> 6   B 70 11
#> 7   C 20  8
#> 8   D 22  9
#> 9   A bA cc
#> 10  B bB dd
#> 11  C bC ee
#> 12  D bD ff

或者更一般的:

n <- 3L # operate on every 3 columns
data.frame(
setNames(
c(
list(dw[,1]),
lapply(
2:(n + 1L),
function(i) unlist(dw[,seq(i, ncol(dw), n)], TRUE, FALSE)
)
),
names(dw)[1:(n + 1L)]
)
)
#>   ID q1 q2 q3
#> 1  A 10  6 50
#> 2  B 12  5 70
#> 3  C 20  7 20
#> 4  D 22  8 22
#> 5  A 10 bA cc
#> 6  B 11 bB dd
#> 7  C  8 bC ee
#> 8  D  9 bD ff

data.tablemelt(...)方法允许熔化列组。使用dw从@r2evans的答案:

library(data.table)
setDT(dw)
result <- melt(dw, measure.vars = list(seq(2, ncol(dw), 2), seq(3, ncol(dw), 2)))
result[, variable:=NULL]
result
##     ID value1 value2
##  1:  A     10      6
##  2:  B     12      5
##  3:  C     20      7
##  4:  D     22      8
##  5:  A     50     10
##  6:  B     70     11
##  7:  C     20      8
##  8:  D     22      9
##  9:  A     bA     zA
## 10:  B     bB     zB
## 11:  C     bC     zC
## 12:  D     bD     zD

melt(...)引入了一个列variable,它跟踪原始列在宽数据集中的位置。你似乎并不在意,所以把它去掉了。如果确实存在不同的类(整数,字符),melt(...)将处理并发出警告。

相关内容

  • 没有找到相关文章

最新更新