我可以根据列的标识来分隔列吗?

Can I separate a column based on its identity?

我是 R 的新手,我想知道是否可以根据列的标识来分隔列?例如,我想将第 5 列分成新列,其中一列中所有以 "E-" 开头的列,另一列中所有以 "D-" 开头的列。

chr1    11046   12418   2   E-H3K27ac,D-Both
chr1    18615   19392   2   D-Both,E-Both
chr1    27209   28559   3   E-H3K4me1,D-Both,E-Both
chr1    35274   35492   1   E-H3K4me1
chr1    36589   38097   2   D-Both,E-Both
chr1    43655   45148   2   D-Both,E-Both
chr1    49265   50054   2   D-Both,E-H3K4me1
chr1    50117   50465   1   E-H3K4me1

所以它看起来像:

chr1    11046   12418   2   E-H3K27ac        D-Both
chr1    18615   19392   2   E-Both           D-Both
chr1    27209   28559   3   E-H3K4me1,E-Both D-Both
chr1    35274   35492   1   E-H3K4me1
chr1    36589   38097   2   E-Both           D-Both
chr1    43655   45148   2   E-Both           D-Both
chr1    49265   50054   2   E-H3K4me1        D-Both
chr1    50117   50465   1   E-H3K4me1

我不确定是否需要先处理包含 3 个条目的行。 (在这个例子中,我可能只是将第 3 行中的 2 个 E- 开始转换为 E-Both)。抱歉,如果已经有人问过类似的问题。我仍在学习行话,所以我对 r 问题的搜索技巧有限。

我们可以用 base R 来做到这一点。用strsplit分隔符,拆分'Col'(如果是factor class,用as.character(df1$Col)包起来)成list,然后paste按第一个字符(substr(x, 1, 1))分组后的元素,sort按降序排列。我们用 NA 填充 list 中只有一个元素的元素,rbind list 元素并创建两个新列 'E_col' 和 'D_col'

lst <- lapply(strsplit(df1$Col, ","), function(x) 
    sort(tapply(x, substr(x, 1, 1), FUN = toString), decreasing=TRUE))
df1[c("E_col", "D_col")] <- do.call(rbind, lapply(lst, `length<-`, max(lengths(lst))))
df1
#   chr   ID1   ID2 val                     Col             E_col  D_col
#1 chr1 11046 12418   2        E-H3K27ac,D-Both         E-H3K27ac D-Both
#2 chr1 18615 19392   2           D-Both,E-Both            E-Both D-Both
#3 chr1 27209 28559   3 E-H3K4me1,D-Both,E-Both E-H3K4me1, E-Both D-Both
#4 chr1 35274 35492   1               E-H3K4me1         E-H3K4me1   <NA>
#5 chr1 36589 38097   2           D-Both,E-Both            E-Both D-Both
#6 chr1 43655 45148   2           D-Both,E-Both            E-Both D-Both
#7 chr1 49265 50054   2        D-Both,E-H3K4me1         E-H3K4me1 D-Both
#8 chr1 50117 50465   1               E-H3K4me1         E-H3K4me1   <NA>

或者另一种选择是使用 splitstackshape 中的 cSplit 拆分 'Col' 并将数据集重塑为 'long' 格式,然后使用 dcast 我们将其更改为 'wide'

library(splitstackshape)
dcast(cSplit(df1, "Col", ",", "long")[, toString(Col) ,
  .(chr, ID1, ID2, val, grp=factor(substr(Col, 1, 1), levels = c("E", "D")))], 
             ... ~ grp, value.var = "V1")

注意:正如@Frank 在评论中建议的那样,最好将其保留为 'long' 格式(cSplit(df1, "Col", ",", "long") 的输出)而不是将其组合回 'wide'格式

数据

df1 <- structure(list(chr = c("chr1", "chr1", "chr1", "chr1", "chr1", 
"chr1", "chr1", "chr1"), ID1 = c(11046L, 18615L, 27209L, 35274L, 
36589L, 43655L, 49265L, 50117L), ID2 = c(12418L, 19392L, 28559L, 
35492L, 38097L, 45148L, 50054L, 50465L), val = c(2L, 2L, 3L, 
1L, 2L, 2L, 2L, 1L), Col = c("E-H3K27ac,D-Both", "D-Both,E-Both", 
"E-H3K4me1,D-Both,E-Both", "E-H3K4me1", "D-Both,E-Both", "D-Both,E-Both", 
"D-Both,E-H3K4me1", "E-H3K4me1")), .Names = c("chr", "ID1", "ID2", 
"val", "Col"), class = "data.frame", row.names = c(NA, -8L))