首页 > 解决方案 > 根据条件将 data.table 列移动到行

问题描述

我有一个像这样设置的大型 data.table:

ID Line.Rec Line.D.Amount Line.Desc Line1.Record Line1.D.Amount Line1.C.Amount Line2.Rec
1  1        100           test      2            500            200            3
2  1        200           testb     2            800            100            3
3  1        600           testc     2            900            500            NA

每个事件/行包含一个 ID 和其他静态列,例如 Eventdate。但是,有不同数量的行(可能从 1 到 99)。行也包含不同数量的列。这些行不是固定的,并且某些文件的行与此不同。因此,我必须使用列名而不是位置。

我希望 data.table 看起来像这样:

ID Record D.Amount C.Amount Description
1  1      100      0        test
1  2      500      200
1  3      0        0        
2  1      200               testb
2  2      800      100    
2  3      0        0  
3  1      600      0        testc
3  2      900      500      

解决方案需要确保与名称的第一部分(line.、line1.、line2.、...line99.)匹配的任何列都包含在正确的行中。ID 行(和 EventDate)需要如图所示包括在内,以确保我可以跟踪哪些行属于一起。

有任何想法吗?

标签: r

解决方案


不是真正的问题。您可能需要考虑更改标签。以下是应该帮助您入门的内容:

library(data.table)
dt <- fread("ID Line.Rec Line.D.Amount Line.Desc Line1.Record Line1.D.Amount Line1.C.Amount Line2.Rec
1  1        100           test      2            500            200            3
2  1        200           testb     2            800            100            3
3  1        600           testc     2            900            500            NA")
#ensure that relevant columns share the same names
setnames(dt, gsub("Rec$", "Record", names(dt)))

#identify which columns forms a sub dataset
otherCols <- setdiff(names(dt), "ID")
groupCols <- split(otherCols, sapply(strsplit(otherCols, "\\."), `[`, 1))
newCols <- sapply(names(groupCols), 
    function(x) gsub(paste0(x, "."), "", groupCols[[x]]))

#take sub columns of original dataset by group    
subDataLs <- lapply(names(groupCols),
    function(x) setnames(dt[, c("ID", groupCols[[x]]), with=FALSE], 
        c("ID", newCols[[x]]))
)

#rbind sub datasets
output <- rbindlist(subDataLs, use.names=TRUE, fill=TRUE)

#format to desired output
cols <- names(output)[sapply(output, is.numeric)]
output[, (cols) := replace(.SD, is.na(.SD), 0), .SDcols=cols]
cols <- names(output)[sapply(output, is.character)]
output[, (cols) := replace(.SD, is.na(.SD), ""), .SDcols=cols]

输出:

   ID Record D.Amount  Desc C.Amount
1:  1      1      100  test        0
2:  2      1      200 testb        0
3:  3      1      600 testc        0
4:  1      2      500            200
5:  2      2      800            100
6:  3      2      900            500
7:  1      3        0              0
8:  2      3        0              0
9:  3      0        0              0

推荐阅读