子字符串和返回字符串

时间:2019-06-20 00:33:03

标签: r dplyr data.table

我想知道是否有一个使用data.table的干净解决方案来解决以下问题,可能使用其他程序包(例如stringer)。

假设我有以下数据表

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                     

,其中每个元素都是一个字符串。我已经能够编写一个代码,该版本使用第一个“美国身份”并丢弃其余的,但我却找不到能够处理多重性的解决方案。

任何帮助将不胜感激!

3 个答案:

答案 0 :(得分: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

答案 1 :(得分: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链中同时包含上述两个选项,但是使用dplyrtidyr的另一个选项将使用separate_rows,这对于这个特定问题可能是过大的了。我们可以使用str_subset中的stringrgrep("^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")))

答案 2 :(得分: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的{​​{1}}

gregexpr