【问题标题】:Splitting the values in column using regex使用正则表达式拆分列中的值
【发布时间】:2015-02-15 11:08:37
【问题描述】:

我的 data.frame 有两列,如下所示

dat

    ID                             Details                         
    id_1        box1_homodomain gn=box1 os=homo sapiens p=4 se=1   
    id_2        sox2_plurinet gn=plu os=mus musculus p=5 se=3 

我想在“详细信息”列中为所有 id 拆分“os=xxx”和 gn="yyy",并按如下方式打印:

    Id   Description        gn      os               
   Îd_1  box1_homodomain    box1    homo sapiens   
   Id_2  sox2_plurinet      plu     mouse musculus 

我尝试在 R 中使用 gsub 方法,但我无法将 os=homo sapiens 和 gn=box1 拆分为各自的列。我使用的以下 R 代码

dat$gn=gsub('^[gn=][A-z][A-z]`,dat$Details)
dat$os=gsub('^[os=][A-z][A-z]`,dat$Details)

谁能告诉我哪里出了问题以及如何纠正。请帮助我。

提前致谢

【问题讨论】:

  • 你的正则表达式似乎工作正常
  • gsub 语法无效,因为它混合了普通的 ' 和反引号,并且因为 gsub 需要 3 个参数,而这里缺少第二个。

标签: regex r split gsub


【解决方案1】:

这是 tidyr 的一个选项:

library(tidyr)
# specify the new column names:
vars <- c("Description", "gn", "os")
# then separate the "Details" column according to regex and drop extra columns:
separate(dat, Details, into = vars, sep = "[A-Za-z]+=", extra = "drop")
#    ID      Description    gn            os
#1 id_1 box1_homodomain  box1  homo sapiens 
#2 id_2   sox2_plurinet   plu  mus musculus

【讨论】:

  • @Thileepan,我不明白你的评论。你能澄清一下你的意思吗?
  • 感谢@docendo discimus。它工作得很好。我还有另一个专栏,GOs。在该列中有 P:pos_1;P:pos_2;F:Fun_1;F:F_2;C:Com_1;C:Com 等值。我想将 thi 列也拆分为 P(应包含以 P:xxx; 开头的所有条目);F(应包含以 F: 开头并以; 结尾的所有条目);C(应包含所有条目以 C:xxx; 开头)。我试过像 "separate(seq, GOs, into = c("P", "F", "C"), sep = "[a-z]+=")" 但它给了我错误
  • 那是另一种情况。您最好将其与示例数据和预期输出一起包含在问题中,以便每个人都可以看到它。您需要调整分割数据的正则表达式。
  • 我可以编辑同一个问题还是应该单独问那个问题。?
  • 如果不是完全不同的情况,您可以在当前问题的底部进行编辑并为另一列添加示例
【解决方案2】:

1) sub 和 gsub 使用subgsub 在问题中尝试这个。请注意,每个正则表达式都应该匹配所有的dat$Details,这样当我们用捕获组替换它时,只剩下捕获组。对于问题的 cmets 中的 dat$GO,我们删除了直到但不包括 P: 的所有内容,用逗号替换所有出现的 ;P 并删除 P: 并删除分号和之后的所有内容。 FC 也是如此:

data.frame(dat[1], 
   Description = sub(" .*", "", dat$Details),
   gn = sub(".*gn=(.*) os=.*", "\\1", dat$Details),
   os = sub(".*os=(.*) p=.*", "\\1", dat$Details),
   P = gsub("P:|;.*", "", gsub(";P:", ",", sub(".*?P:", "P:", dat$GO))),
   F = gsub("F:|;.*", "", gsub(";F:", ",", sub(".*?F:", "F:", dat$GO))),
   C = gsub("C:|;.*", "", gsub(";C:", ",", sub(".*?C:", "C:", dat$GO))))

给予:

    ID     Description   gn           os       P       F       C
1 id_1 box1_homodomain box1 homo sapiens p_1,p_2     F_1 C_1,C_2
2 id_2   sox2_plurinet  plu mus musculus     p_1 F_1,F_2     C_1

2) read.pattern 使用read.pattern (link)gsubfn package 中处理dat$Details 会更容易一些,因为可以定义一个单个 正则表达式,其捕获组代表感兴趣的领域。 dat$GO 的处理也可以通过使用strapplyc(link) 提取P:... 字段,然后将它们与paste 连接在一起来简化(与FC 字段类似):

library(gsubfn)

Sub <- function(string, pat) sapply(strapplyc(string, pat), paste, collapse = ",")

DF <- read.pattern(text = as.character(dat$Details), 
        pattern = "(.*) gn=(.*) os=(.*) p=",
        col.names = c("Description", "gn", "os"),
        as.is = TRUE)

cbind(dat[1], DF,
      P = Sub(dat$GO, "P:(.*?);"),
      F = Sub(dat$GO, "F:(.*?);"),
      C = Sub(dat$GO, "C:(.*?);"))

给予:

    ID     Description   gn           os       P       F       C
1 id_1 box1_homodomain box1 homo sapiens p_1,p_2     F_1 C_1,C_2
2 id_2   sox2_plurinet  plu mus musculus     p_1 F_1,F_2     C_1

这是read.pattern中使用的正则表达式的可视化:

(.*) gn=(.*) os=(.*) p=

Debuggex Demo

备注

1) 如果dat$Details 列已经是字符,我们可以省略as.character。如果可以在结果中包含 factor 列,我们也可以省略 as.is=TRUE

2) 问题中的示例输出为mouse,但输入为mus。我们假设在这两种情况下都应该是mus

3) 我们将其用于dat

dat <-
structure(list(ID = c("id_1", "id_2"), 
Details = c("box1_homodomain gn=box1 os=homo sapiens p=4 se=1", 
"sox2_plurinet gn=plu os=mus musculus p=5 se=3"), 
GO = c("P:p_1;P:p_2;F:F_1;C:C_1;C:C_2;  ", 
"P:p_1;F:F_1;F:F_2;C:C_1;")), .Names = c("ID", "Details", 
"GO"), class = "data.frame", row.names = c(NA, -2L))

以后请在问题中发布dput(dat)的结果。

【讨论】:

  • 添加了dat$GO根据海报的cmets的处理和一些改进。
【解决方案3】:

您也可以为此使用正则表达式捕获组。 每个捕获组匹配可以用例如提取stringi 包中的 stri_match_first_regex 函数。

dat <- data.frame(
   ID=c("id_1", "id_2"),
   details=c("box1_homodomain gn=box1 os=homo sapiens p=4 se=1", "sox2_plurinet gn=plu os=mus musculus p=5 se=3")
)

library(stringi)
res <- stri_match_first_regex(dat$details, "^(.+) gn=(.+) os=(.+) p=.*$")
res[,1] <- dat$ID
res <- as.data.frame(res)
names(res) <- c("ID", "Description", "gn", "os")
res
##   ID     Description   gn           os
## 1  1 box1_homodomain box1 homo sapiens
## 2  2   sox2_plurinet  plu mus musculus

【讨论】:

    猜你喜欢
    • 2021-04-23
    • 2020-08-07
    • 2020-08-25
    • 2020-06-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多