Переименование «грязных» имен уровня данных - PullRequest
0 голосов
/ 10 мая 2018

У меня "грязный" фрейм данных с именами уровней факторов повсюду

DF <- data.frame(V1 = factor(c("A.", "zB,", "Cs", "At", "Dp", "Df")),
                   V2=factor(c("Af", "A_", "A_", ".A", "D.", "rB")))

Я хочу переименовать свои уровни, чтобы у меня были только уровни A, B, C и D.

Я могу сделать это для каждого отдельного уровня, используя:

as.data.frame(lapply(DF, function(x) { revalue(x, c("A."="A")) }))

Но это занимает много времени для большого кадра данных.

Есть ли способ автоматизировать это, чтобы каждый уровень, содержащий букву "A", был переименован в A (называется ли он A. или Af) и т. Д .?

Ответы [ 3 ]

0 голосов
/ 10 мая 2018

В этом примере вы можете сделать это быстро с помощью stringr::str_extract и применить к каждому столбцу с помощью mutate_all из dplyr

library(dplyr)
DF %>% mutate_all(stringr::str_extract, "[A-D]")
  V1 V2
1  A  A
2  B  A
3  C  A
4  A  A
5  D  D
6  D  B
0 голосов
/ 10 мая 2018

Так как вам нужно извлечь заглавную букву, A, B, C или D из каждого элемента, хорошо подходит регулярное выражение для извлечения совпадений для "[A-D]".

Вот 3 способав зависимости от предпочтений.Первый использует lapply, чтобы применить regmatches и regexpr к каждому столбцу.Второй использует lapply для применения str_extract от stringr, который является оберткой вокруг stri_extract от stringi.Третий пропускает lapply и вместо этого использует mutate_all из dplyr, чтобы применить функцию ко всем столбцам (или mutate_at, если вам нужно это для подмножества столбцов), и снова str_extract.

DF <- data.frame(V1 = factor(c("A.", "zB,", "Cs", "At", "Dp", "Df")),
                                 V2=factor(c("Af", "A_", "A_", ".A", "D.", "rB")))

as.data.frame(lapply(DF, function(x) regmatches(x, regexpr("[A-D]", x))))
#>   V1 V2
#> 1  A  A
#> 2  B  A
#> 3  C  A
#> 4  A  A
#> 5  D  D
#> 6  D  B

as.data.frame(lapply(DF, function(x) stringr::str_extract(x, "[A-D]")))
#>   V1 V2
#> 1  A  A
#> 2  B  A
#> 3  C  A
#> 4  A  A
#> 5  D  D
#> 6  D  B

library(tidyverse)
DF %>% mutate_all(str_extract, "[A-D]")
#>   V1 V2
#> 1  A  A
#> 2  B  A
#> 3  C  A
#> 4  A  A
#> 5  D  D
#> 6  D  B

Создано в 2018-05-10 пакетом Представ (v0.2.0).

0 голосов
/ 10 мая 2018

Вот довольно общее решение.

#' @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 на тот случай, если вы хотите сделать его нечувствительным к регистру, использовать фиксированный шаблон вместо регулярных выражений и т. Д.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...