重组和格式化数据框列

Restructuing and formatting data frame columns

dfin <- 

ID   SEQ   GRP   C1   C2   C3   T1   T2   T3
1     1     1    0     5    8   0     1   2
1     2     1    5     10   15  5     6   7
2     1     2    20    25   30  0     1   2

C1是T1(TIME)时的浓度(CONC),依此类推。这就是我想要的输出:

dfout <- 

ID   SEQ   GRP  CONC  TIME
1     1     1    0     0
1     1     1    5     1
1     1     1    8     2
1     2     1    5     5
1     2     1    10    6
1     2     1    15    7
2     1     2    20    0
2     1     2    25    1
2     1     2    30    2

dfin CxTx 的列更多,其中 x 是浓度读数的数量。

您可以使用 data.table::melt 执行此操作,它能够根据列模式将 table 融合为多列:

library(data.table)
melt(
    setDT(df), 
    id.vars=c("ID", "SEQ", "GRP"), 
    # columns starts with C and T should be melted into two separate columns
    measure.vars=patterns("^C", "^T"),     
    value.name=c('CONC', 'TIME')
)[order(ID, SEQ)][, variable := NULL][]

#   ID SEQ GRP CONC TIME
#1:  1   1   1    0    0
#2:  1   1   1    5    1
#3:  1   1   1    8    2
#4:  1   2   1    5    5
#5:  1   2   1   10    6
#6:  1   2   1   15    7
#7:  2   1   2   20    0
#8:  2   1   2   25    1
#9:  2   1   2   30    2

或者如果值列名称遵循模式 [CT][0-9],您可以通过指定 sep="" 使用基数 R 中的 reshape,这将按 [= 拆分值列名称23=] 由于此默认设置而分离(来自?reshape):

split = if (sep == "") {
            list(regexp = "[A-Za-z][0-9]", include = TRUE)
        } else {
            list(regexp = sep, include = FALSE, fixed = TRUE)}
reshape(df, varying=-(1:3), idvar=c("ID", "SEQ", "GRP"), 
        dir="long", sep="", v.names=c("CONC", "TIME"))

#   ID SEQ GRP time CONC TIME
#1:  1   1   1    1    0    5
#2:  1   2   1    1    5   10
#3:  2   1   2    1   20   25
#4:  1   1   1    2    8    0
#5:  1   2   1    2   15    5
#6:  2   1   2    2   30    0
#7:  1   1   1    3    1    2
#8:  1   2   1    3    6    7
#9:  2   1   2    3    1    2