【问题标题】:R regular expression to split string column into multiple columnsR正则表达式将字符串列拆分为多列
【发布时间】:2015-03-31 05:21:02
【问题描述】:

我在名为 PeakBoundaries 的数据框中有一列如下:

           chrom
 chr11:69464719-69502928
 chr7:55075808-55093954
 chr8:128739772-128762863
 chr3:169389459-169490555
 chr17:37848534-37877201
 chr19:30306758-30316875
 chr1:150496857-150678056
 chr12:69183279-69260755
 chr11:77610143-77641464
 chr8:38191804-38260814
 chr12:58135797-58156509

我想将列分开,以便数据框中的列如下所示:

chr       chrStart           chrEnd
chr11     69464719         69502928
chr7      55075808         55093954
chr8      128739772        128762863
chr3      169389459        169490555

等等

我尝试了正则表达式方法,但在让匹配项进入新列方面没有取得任何进展:

 PeakBoundaries$chrOnly <- PeakBoundaries[grep("\\w+?=\\:"),PeakBoundaries$chrom]

我遇到了错误: [.data.frame(PeakBoundaries, grep("\w+?=\:"), PeakBoundaries$chrom) 中的错误: 选择了未定义的列

【问题讨论】:

  • PeakBoundaries 还是PeakBoudaries
  • 峰边界。那是问题中的错字而不是代码;)
  • 请更正。 “PeakBoundaries”中的列名称中是否有多余的空格?
  • 没有多余的空格

标签: regex r split multiple-columns


【解决方案1】:

试试这个 - 不需要正则表达式,只需 strsplit 函数:

dat <- read.table(text="chr11:69464719-69502928
chr7:55075808-55093954
chr8:128739772-128762863
chr3:169389459-169490555
chr17:37848534-37877201
chr19:30306758-30316875
chr1:150496857-150678056
chr12:69183279-69260755
chr11:77610143-77641464
chr8:38191804-38260814
chr12:58135797-58156509", stringsAsFactors=FALSE)

dat[,2:4] <- matrix(unlist(strsplit(dat[,1],split = "\\:|\\-")), ncol=3, byrow=TRUE)

colnames(dat) <- c("chrom", "chr", "chrStart", "chrEnd")

# Convert last two columns from character to numeric:

dat$chrStart <- as.numeric(dat$chrStart)
dat$chrEnd <- as.numeric(dat$chrEnd)

结果

> res

                      chrom   chr  chrStart    chrEnd
1   chr11:69464719-69502928 chr11  69464719  69502928
2    chr7:55075808-55093954  chr7  55075808  55093954
3  chr8:128739772-128762863  chr8 128739772 128762863
4  chr3:169389459-169490555  chr3 169389459 169490555
5   chr17:37848534-37877201 chr17  37848534  37877201
6   chr19:30306758-30316875 chr19  30306758  30316875
7  chr1:150496857-150678056  chr1 150496857 150678056
8   chr12:69183279-69260755 chr12  69183279  69260755
9   chr11:77610143-77641464 chr11  77610143  77641464
10   chr8:38191804-38260814  chr8  38191804  38260814
11  chr12:58135797-58156509 chr12  58135797  58156509

编辑

您可以仅使用现有数据框完成所有操作。将dat[,1] 替换为PeakBoundaries$chrom,将dat[,2:4] 替换为PeakBoundaries[,(ncol(PeakBoundaries)+1):(ncol(PeakBoundaries)+3)],您应该拥有它!

由 OP 编辑​​

好的,所以我认为我的数据集有些奇怪,但我在 Dominic 的帮助下对其进行了排序,现在是这样:

  PeakBoundaries <- as.data.frame(PeakBoundaries)
  PeakBoundaries <- PeakBoundaries[-1,]
  PeakBoundaries <- as.data.frame(PeakBoundaries)
  PeakBoundaries$PeakBoundaries <- 
             as.character(PeakBoundaries$PeakBoundaries)
  PeakBoundaries[,(ncol(PeakBoundaries)+1):(ncol(PeakBoundaries)+3)] <- 
             matrix(unlist(strsplit(PeakBoundaries$PeakBoundaries,
                                    split = "\\:|\\-")), ncol=3, byrow=TRUE)

【讨论】:

  • 好的,谢谢。如何将我的列数据放入您建议作为数据输入的表中?
  • 好的。现在我在 strsplit(PeakBoundaries$chrom, split = "\\:|\\-") 中出现错误 Error : non-character argument
  • 你确定你的专栏叫“chrom”吗?
  • colnames(PeakBoundaries) [1] "chrom"
  • 好的,那就试试as.character(PeakBoundaries$chrom)吧。这可能是一个因素。
【解决方案2】:

多米尼克答案的较短版本,使插入成为单行:

dat <- data.frame(chrom = readLines(textConnection("chr11:69464719-69502928
chr7:55075808-55093954
chr8:128739772-128762863
chr3:169389459-169490555
chr17:37848534-37877201
chr19:30306758-30316875
chr1:150496857-150678056
chr12:69183279-69260755
chr11:77610143-77641464
chr8:38191804-38260814
chr12:58135797-58156509")) )

dat[, c('chr','chrStart','chrEnd')] <- t( sapply( dat$chrom, function(s) { str_split(s, '[:-]') [[1]] } ) )

dat$chrStart <- as.numeric(dat$chrStart)
dat$chrEnd <- as.numeric(dat$chrEnd)

【讨论】:

  • 我认为我遇到的问题之一是将数据框中的列转换为文本格式,以便可以完成 read.table。我从 Dominica 较早的回答中猜测,我可以直接使用数据框中的列,而无需通过读取表步骤?
  • 我刚刚发布了你上面的代码! dat &lt;- data.frame(chrom = readLines(textConnection(... 而不是 read.table(text=..., header = F)
【解决方案3】:

我们可以试试

library(tidyr)
extract(dat, chrom, into=c('chr', 'chrStart', 'chrEnd'),
                 '([^:]+):([^-]+)-(.*)', convert=TRUE)
#     chr  chrStart    chrEnd
#1  chr11  69464719  69502928
#2   chr7  55075808  55093954
#3   chr8 128739772 128762863
#4   chr3 169389459 169490555
#5  chr17  37848534  37877201
#6  chr19  30306758  30316875
#7   chr1 150496857 150678056
#8  chr12  69183279  69260755
#9  chr11  77610143  77641464
#10  chr8  38191804  38260814
#11 chr12  58135797  58156509

或者使用data.table 的开发版本的更快选项。我们可以从here 安装v1.9.5

library(data.table) # v1.9.5+
nm1 <- c('chr', 'chrStart', 'chrEnd')
res <- setDT(tstrsplit(dat$chrom, '[:-]', type.convert=TRUE))
setnames(res, nm1)
res
#      chr  chrStart    chrEnd
# 1: chr11  69464719  69502928
# 2:  chr7  55075808  55093954
# 3:  chr8 128739772 128762863
# 4:  chr3 169389459 169490555
# 5: chr17  37848534  37877201
# 6: chr19  30306758  30316875
# 7:  chr1 150496857 150678056
# 8: chr12  69183279  69260755
# 9: chr11  77610143  77641464
#10:  chr8  38191804  38260814
#11: chr12  58135797  58156509

或者

library(splitstackshape)
setnames(cSplit(dat, 'chrom', ':|-',fixed=FALSE,
                      type.convert=TRUE), nm1)[]

数据

dat <- structure(list(chrom = structure(c(2L, 9L, 10L, 8L, 6L, 7L, 1L, 
5L, 3L, 11L, 4L), .Label = c("chr1:150496857-150678056",
"chr11:69464719-69502928", 
"chr11:77610143-77641464", "chr12:58135797-58156509", 
"chr12:69183279-69260755", 
"chr17:37848534-37877201", "chr19:30306758-30316875",
 "chr3:169389459-169490555", 
"chr7:55075808-55093954", "chr8:128739772-128762863",
 "chr8:38191804-38260814"
 ), class = "factor")), .Names = "chrom", row.names = c(NA, -11L
 ), class = "data.frame")

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多