1

我想知道是否有使用 data.table 解决以下问题的干净解决方案,可能使用其他包,例如 stringr。

假设我有以下数据表

DT <- data.table(name = c("Carlos", "Henry", "John"), 
    ID = c("US115115, CH123232, AB155, US4445", "CH112, BB53", "US57677777"))

这看起来像:

     name                                ID
1: Carlos US115115, CH123232, AB155, US4445
2:  Henry                       CH112, BB53
3:   John                        US57677777

我想要做的是创建另一列 ID2,例如,它采用列 ID 并仅提取“美国身份”并创建一个新列,以便最终数据表应如下所示:

     name                                ID              ID2
1: Carlos US115115, CH123232, AB155, US4445 US115115, US4445
2:  Henry                       CH112, BB53               NA
3:   John                        US57677777       US57677777                     

并且每个元素都是一个字符串。我已经能够编写一个版本,它采用第一个“美国身份”并丢弃其余部分,但我无法找到处理多重性的解决方案。

任何帮助将不胜感激!

4

3 回答 3

4

一种可能的方法:

DT[, ID2 := sapply(strsplit(ID, ","), 
    function(s) paste(s[grepl("\\s*US", s)], collapse=","))]

输出:

     name                                ID              ID2
1: Carlos US115115, CH123232, AB155, US4445 US115115, US4445
2:  Henry                       CH112, BB53                 
3:   John                        US57677777       US57677777
于 2019-06-20T00:48:48.363 回答
2

以下是受@thelatemail 和@chinsoon12 启发的一些建议

DT$ID1 <- sapply(strsplit(DT$ID, ",\\s*"), function(x) 
                            toString(grep("^US", x, value = TRUE)))
DT
#     name                                ID              ID1
#1: Carlos US115115, CH123232, AB155, US4445 US115115, US4445
#2:  Henry                       CH112, BB53                 
#3:   John                        US57677777       US57677777

上面我们是用 过滤的grep,我们也可以用startsWith来做同样的事情

sapply(strsplit(DT$ID, ",\\s*"), function(x) toString(x[startsWith(x, "US")]))

dplyr您可以在链中合并上述两个选项,但是另一个选项正在使用dplyr并且tidyr将使用separate_rows这对于这个特定问题可能是过度杀伤力。我们可以使用str_subsetfrom stringrwhich is the same as grep("^US", x, value = TRUE)

library(dplyr)
library(tidyr)

DT %>%
  separate_rows(ID) %>%
  group_by(name) %>%
  summarise(ID1 = toString(ID), 
            ID2 = toString(stringr::str_subset(ID, "^US")))
于 2019-06-20T02:23:08.917 回答
0

我们可以str_extract用来提取以“US”开头的单词

library(stringr)
DT[, ID2 := sapply(str_extract_all(ID, "\\bUS\\S*"), toString)]
DT
#     name                                ID               ID2
#1: Carlos US115115, CH123232, AB155, US4445 US115115,, US4445
#2:  Henry                       CH112, BB53                  
#3:   John                        US57677777        US57677777

或使用gsub

DT[, ID2 := gsub("(\\bUS\\S*)(*SKIP)(*F)|.", "", ID, perl = TRUE)]

或使用tidyverse

library(tidyverse)
DT %>%
    mutate(ID2 = str_extract_all(ID, "\\bUS\\S*") %>%
                   map(toString))

base R使用gregexpr

DT$ID2 <- sapply(regmatches(DT$ID, gregexpr("\\bUS\\S*", DT$ID)), toString)
于 2019-06-20T02:42:30.837 回答