如何在R中编辑colnames?

时间:2014-05-28 17:30:10

标签: regex r

我有一个名为 name 的变量,我想将其设置为我的矩阵的列名,但在此之前,我需要编辑名为 name

>name
[722] "TCGA-OL-A66N-01A-12R-A31S-13.isoform.quantification.txt"
[723] "TCGA-OL-A66O-01A-11R-A31S-13.isoform.quantification.txt"
[724] "TCGA-OL-A66P-01A-11R-A31S-13.isoform.quantification.txt"

我想在第四个 -

之前保留字母

预期产出:

  >name
    [722] "TCGA-OL-A66N-01A"
    [723] "TCGA-OL-A66O-01A"
    [724] "TCGA-OL-A66P-01A"

有人会帮我在R中实现这个吗?

5 个答案:

答案 0 :(得分:8)

正则表达式" ["运算符定义了一个字符类,在字符类中定义了" ^"第一个位置的算子做否定;

?regex
?sub

sub("^([^-]*[-][^-]*[-][^-]*[-][^-]*)([-].*$)", "\\1", name)
[1] "TCGA-OL-A66N-01A" "TCGA-OL-A66O-01A" "TCGA-OL-A66P-01A"

这比str_split方法

更简单(IMO)
 sapply( lapply( strsplit(name, "\\-"), "[", 1:4),   
                # extracted the first 4 elements from each list element returned by strsplit
         paste, collapse="-")  # 'collapse' needed rather than 'sep'

#[1] "TCGA-OL-A66N-01A" "TCGA-OL-A66O-01A" "TCGA-OL-A66P-01A"

答案 1 :(得分:5)

如果尺寸变化/不能保证nchar,您可以使用str_split_fixed()中的stringr

stringr解决方案:

library(stringr)

name <- c(
    "TCGA-OL-A66N-01A-12R-A31S-13.isoform.quantification.txt",
    "TCGA-OL-A66O-01A-11R-A31S-13.isoform.quantification.txt",
    "TCGA-OL-A66P-01A-11R-A31S-13.isoform.quantification.txt")

apply(str_split_fixed(name,"-",5)[,1:4],1,paste0,collapse="-")

会给你什么:

## "TCGA-OL-A66N-01A" "TCGA-OL-A66O-01A" "TCGA-OL-A66P-01A"

解释

  • str_split_fixed(name,"-",5)

根据name

的前5个部分将5的每个向量元素拆分为-个部分
  • [,1:4]

保留每个name元素的前4个部分(结果矩阵的列)

  • apply(...,1,paste0,collapse="-")

将它们粘贴在一起使用"-"折叠以恢复名称(按行)


但如果我有很多名字呢?

我在这里将stringr + apply()方法与@BondedDust grep方法和基本strsplit方法进行比较。

首先,让我们将它提升到一万个名字:

name <- rep(name,3.334e3)

然后是一个微基准:

microbenchmark(
  stringr_apply = apply(str_split_fixed(name,"-",5)[,1:4],1,paste0,collapse="-"),
  grep_ninja = sub("^([^-]*[-][^-]*[-][^-]*[-][^-]*)([-].*$)", "\\1", name),
  strsplit = sapply( lapply( strsplit(name, "\\-"), "[", 1:4), paste, collapse="-"), 
  times=25)

并获得:

#  Unit: milliseconds
#  expr             min       lq    median        uq       max    neval
# stringr_apply 845.44542 874.5674 899.27849 941.22628 976.88903    25
# grep_ninja     25.51796  25.7066  25.85404  25.95922  27.89165    25
# strsplit      115.10626 123.2645 126.45171 130.10334 147.39517    25

似乎base模式匹配/替换会更好地扩展......大约一秒钟或比最慢的方式快30倍。

答案 2 :(得分:2)

我想你可能想要substr

names <- substr(names,start=1,stop=16)
colnames(myDF) <- names

这将使用您指定的子字符串覆盖原始namesnames是您的名称变量,start是第一个字符,stop是最后一个字符。然后,您可以使用names覆盖data.frame或其他任何内容的名称。

答案 3 :(得分:1)

stringr包的另一个选项(虽然比@ BondedDust的答案慢得多):

library('stringr')
str_match(name, "^([^-]*[-][^-]*[-][^-]*[-][^-]*)")[, 1]

答案 4 :(得分:1)

如果所有第五组字母数字以R结尾,

> txt <- c("TCGA-OL-A66N-01A-12R-A31S-13.isoform.quantification.txt",
           "TCGA-OL-A66O-01A-11R-A31S-13.isoform.quantification.txt",
           "TCGA-OL-A66P-01A-11R-A31S-13.isoform.quantification.txt")

> gsub("-[0-9]{2}R.*", "", txt)
# [1] "TCGA-OL-A66N-01A" "TCGA-OL-A66O-01A" "TCGA-OL-A66P-01A"

或者相同的块始终以1开头,但不会以R结尾。

> gsub("-[1-9]{2}[A-Z]{1}.*", "", txt)

你也可以在strsplit中使用正则表达式,我在其他回复中没有看到太多。

> unlist(strsplit(txt, "-[1-9]{2}[A-Z].*"))
# [1] "TCGA-OL-A66N-01A" "TCGA-OL-A66O-01A" "TCGA-OL-A66P-01A"

我寻找一个好的模式,以避免写一个过长,混乱的正则表达式。