R从宽到长用列名重塑

R wide to long reshape with column names

我有这种格式的数据

A1 A2 B1 B2  C1  C2
10  5 11  5  21  10

我想将其转换为:

  1  2
A 10 5
B 11 5
C 21 10

如何在 R 中实现?

我们可以 gather 变成 'long' 格式,然后 separate 'key' 列在数字部分之前分成两列, spread 它到 'wide' 并将 'key1' 列更改为行名称

library(tidyverse)
gather(df1) %>%
    separate(key, into = c('key1', 'key2'), sep="(?=\d)") %>% 
    spread(key2, value) %>% 
    column_to_rownames('key1')
#  1  2
#A 10  5
#B 11  5
#C 21 10

数据

df1 <- structure(list(A1 = 10L, A2 = 5L, B1 = 11L, B2 = 5L, C1 = 21L, 
     C2 = 10L), class = "data.frame", row.names = c(NA, -1L))

一个data.table解决方案:

library(data.table)
library(magrittr)
melt(df1, measure.vars = names(df1)) %>%
  .[, c("l", "n") := tstrsplit(variable, "")] %>%
  dcast(l ~ n)

   l  1  2
1: A 10  5
2: B 11  5
3: C 21 10

问题的标签是 r、reshape 和 reshape2,因此我们展示了使用其中每一个的解决方案。

1) xtabs 基本的 R 解决方案如下。

let <- gsub("\d", "", names(DF))
num <- gsub("\D", "", names(DF))
tab <- xtabs(unlist(DF) ~ let + num)

给予:

> tab
   num
let  1  2
  A 10  5
  B 11  5
  C 21 10

或数据框:

cbind(let = rownames(tab), as.data.frame.matrix(tab))

给予:

  let  1  2
A   A 10  5
B   B 11  5
C   C 21 10

2) reshape 另一个基本的 R 解决方案如下。 letnum来自上面。

varying <- split(names(DF), num)
reshape(DF, dir = "long", varying = varying, v.names = names(varying),
  times = unique(let), timevar = "let")[-4]

给予:

    let  1  2
1.A   A 10  5
1.B   B 11  5
1.C   C 21 10

3) reshape2 使用上面的 letnum

library(reshape2)

dcast(let ~ num, data = data.frame(value = unlist(DF)), value.var = "value")

给予:

  let  1  2
1   A 10  5
2   B 11  5
3   C 21 10

备注

可重现形式的输入:

Lines <- "
A1 A2 B1 B2  C1  C2
10  5 11  5  21  10"
DF <- read.table(text = Lines, header = TRUE)