簡體   English   中英

R - 從字符串中提取不匹配其他字符串的元素

[英]R - extract elements from character string that NOT match other string

我想從一個字符串中提取不在另一個字符串中的元素。

最快的(矢量化?)方法是什么?

模擬數據:

library(data.table)
dt <- data.table(id = c("A", "B", "C", "D"),
             product= c("1", "1,2", "1,2,3", "4"),
             stock= c("2, 3", "1,2", "1,2", "4"))

> dt
   id product stock
1:  A       1  2, 3
2:  B     1,2   1,2
3:  C   1,2,3   1,2
4:  D       4     4

我正在尋找的是一個名為new的新變量,它保存product中沒有stock的元素。

> dt
   id product stock  new
1:  A       1  2, 3    1
2:  B     1,2   1,2 <NA>
3:  C   1,2,3   1,2    3
4:  D       4     4 <NA>

注意:它似乎與stringr::str_extract_all完全相反,但此函數沒有negate函數。

這里是一個選項,通過分裂感興趣的列strssplit ,使用setdiff找到elemens沒有第二個。 如果沒有值,即如果length 0,則返回NA

f1 <- function(x, y) {
    x1 <- setdiff(x, y)
   if(!length(x1)) NA_character_ else x1
 }

dt[, new := do.call(Map, c(f = f1,
    unname(lapply(.SD, strsplit, ",")))), .SDcols = 2:3]
dt
#   id product stock  new
#1:  A       1  2, 3    1
#2:  B     1,2   1,2 <NA>
#3:  C   1,2,3   1,2    3
#4:  D       4     4 <NA>

或者,如果我們需要使用str_extract_all , tidyverse 選項將是

library(tidyverse)
dt %>% 
   mutate_at(2:3, list(newvar = ~ str_extract_all(., '\\d+'))) %>%  
   transmute(id, product, stock, new = map2(product_newvar, stock_newvar, f1))

僅使用basedata.table ,我們並行循環遍歷兩列並使用setdiff ,然后添加 NA 並使其成為原子向量:

dt[,new:= mapply(setdiff, strsplit(product, ","), strsplit(stock, ","))]
is.na(dt$new) <- !lengths(dt$new)
dt$new <- unlist(dt$new)
dt
#>    id product stock new
#> 1:  A       1  2, 3   1
#> 2:  B     1,2   1,2  NA
#> 3:  C   1,2,3   1,2   3
#> 4:  D       4     4  NA

這是純data.table代碼:

dt[,new:= mapply(setdiff, strsplit(product, ","), strsplit(stock, ","))][
  lengths(new) == 0, new := NA][
    , new := unlist(new)]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM