#r #data.table
#r #данные.таблица
Вопрос:
Я пытаюсь создать %in%
подобную функцию без учета регистра. Я до сих пор создавал это:
qs <- function(str, vec, na.rm = TRUE) {
stopifnot("str must have length 1" = length(str) == 1)
if(na.rm) {
any(stringi::stri_detect_fixed(str, na.omit(vec), max_count = 1, opts_fixed = list(case_insensitive = TRUE)))
} else {
any(stringi::stri_detect_fixed(str, vec, max_count = 1, opts_fixed = list(case_insensitive = TRUE)))
}
Для моего варианта использования мне нужно это векторизовать, чтобы я мог сделать:
vecqs <- Vectorize(qs, "str")
Однако я читал, что Vectorize
это довольно медленно. Я также читал о data.table::chmatch
и fastmatch
пакете. Оба они реализуют свою собственную %in%
функцию типа ( chmatch
для data.table
). Это было бы здорово, но я не знаю, как сделать chmatch
без учета регистра.
Комментарии:
1. вы могли бы просто использовать
tolower(X) %in% tolower(Y)
, который не учитывал бы регистр, поскольку все преобразуется в нижний регистр. Только незначительные улучшения были бы получены при использованииRcpp
функции, использующей таблицу поиска ASCI или UTF-8, которая итеративно сопоставляет строки (если они вообще есть).2. с помощью data.table можно создать фиктивный столбец
dat[,to_match:=toupper(target][,to_match%chin%list_of_matches]
, а затем удалить фиктивный столбец (или просто объединить)3. Нет причин для назначения фиктивного столбца. Просто используйте
tolower
илиtoupper
для каждого аргумента при сравнении%chin%
.
Ответ №1:
Основываясь на комментариях выше, я пришел к относительно простому решению, приведенному ниже:
#' Quick Search
#'
#' Quick case-insensitive search of strings in a character vector
#'
#' @param str a character vector: the values to be matched
#' @param vec a character vector: the values to be matched against
#'
#' @details Utilizes code{data.table::`%chin%`} to rapidly complete a case-insensitive search
#' through a character vector to return a logical vector of string detections.
#' Will always return TRUE or FALSE for each position of code{str} regardless of NA missing values
#' in either provided vector. NA in code{str} will never match an NA value in code{vec}.
#'
#' @return a logical vector of length code{length(str)}
#'
#' @export
#' @importFrom data.table %chin%
#'
#' @examples
#' x <- c("apple","banana","cherry",NA)
#' "apple" %qsin% x
#' c("APPLE","BANANA","coconut", NA) %qsin% x
#'
`%qsin%` <- function(str, vec) {
tolower(str) %chin% na.omit(tolower(vec))
}
Комментарии:
1. возможно, потребуется добавить явное,
if (!require("data.table")) ...
если это не используется в контексте, гдеdata.table
обязательно будет загружено. (Я пропустилdata.table::
в документах в первый раз)