Вот довольно общее решение.
#' @description Renames factor levels containing a pattern
#' @details If an input element matches more than one pattern, the first will be used.
#' @param f Factor or character vector to modify
#'
#' @param pattern Pattern to match (regex optional)
#' @param label Label to assign for each pattern. Defaults to the pattern
#' @param ... Extra arguments passed to `grep`
#' @return Vector of the same type as `f`, with any elements matching a `pattern`
#' replaced by the corresponding `label`.
#'
#' @author Gregor Thomas
contain_relabel = function(f, pattern, label= pattern, ...) {
if (length(pattern) != length(label)) stop("pattern and label must have same")
is_input_factor = is.factor(f)
f = as.character(f)
for (i in seq_along(pattern)) {
f[grep(pattern[i], f, ...)] = label[i]
}
if (is_input_factor) return(factor(f))
return(f)
}
V1 = factor(c("A.", "zB,", "Cs", "At", "Dp", "Df"))
contain_relabel(V1, "A")
# [1] A zB, Cs A Dp Df
# Levels: A Cs Df Dp zB,
contain_relabel(V1, LETTERS[1:4])
# [1] A B C A D D
# Levels: A B C D
Как и любая другая функция, которая принимает и возвращает вектор, вы можете использовать lapply
в вашем фрейме данных, чтобы применить его ко всем столбцам:
DF[] = lapply(DF, contain_relabel, pattern = LETTERS[1:4])
DF
# V1 V2
# 1 A A
# 2 B A
# 3 C A
# 4 A A
# 5 D D
# 6 D B
Вы можете применить его только к столбцам фактора с
fc = sapply(DF, is.factor)
DF[fc] = lapply(DF[fc], ...<same as above>...)
Общим является то, что по умолчанию оно переименовывается в соответствие шаблону, как указано выше, но вы также можете быть более гибкими. Например, если вы хотите, чтобы что-либо, содержащее «A», было переименовано в «Alpha», вы можете сделать contain_relabel(x, "A", "Alpha")
. Вы также можете использовать ...
для передачи аргументов в grep
на тот случай, если вы хотите сделать его нечувствительным к регистру, использовать фиксированный шаблон вместо регулярных выражений и т. Д.