Фактор неизвестных уровней во время выполнения при установке меток для известных уровней во время разработки

Рассмотрим простую функцию, которая факторизует и помечает вектор (с неупорядоченными уровнями):

  my.factor <- function(data){
    levels = c("d1", "d2", "d3")
    labels = c("Data 1", "Data 2", "Data 3")
    factored.data = factor(data, levels, labels)
    factored.data
  }

Это хорошо работает для известных уровней. Но предположим, что в будущем будет добавлен неизвестный уровень, и мы запустим нашу функцию:

data = c("d1", "d2", "d3", "d1", "d100")
my.factor(data)

Вывод будет:

# [1] Data 1 Data 2 Data 3 Data 1 <NA>  
# Levels: Data 1 Data 2 Data 3

Однако я хочу, чтобы новое неизвестное значение было включено в качестве уровня. То есть я хочу, чтобы вывод напоминал:

# [1] Data 1 Data 2 Data 3 Data 1 d100
# Levels: Data 1 Data 2 Data 3 d100

Есть ли способ установить метки для известных уровней во время разработки, в то же время включая новые, неизвестные уровни, которые могут быть переданы моему коду во время выполнения?


person user1393477    schedule 16.04.2015    source источник
comment
Имеет ли значение порядок результирующих уровней?   -  person David Robinson    schedule 16.04.2015
comment
@DavidRobinson Уровни неупорядочены, я должен был указать и отредактировать вопрос. Ценю ваше четкое, лаконичное решение.   -  person user1393477    schedule 16.04.2015


Ответы (3)


Вы могли бы сделать

  my.factor <- function(data){
    levels <- c("d1", "d2", "d3")
    labels <- c("Data 1", "Data 2", "Data 3")
    nlevels <- setdiff(unique(data), levels)
    levels<-c(levels, nlevels)
    labels <-c(labels, nlevels)
    factored.data = factor(data, levels, labels)
    factored.data
  }

который дает

data = c("d1", "d2", "d3", "d1", "d100")
my.factor(data)
# [1] Data 1 Data 2 Data 3 Data 1 d100  
# Levels: Data 1 Data 2 Data 3 d100
person MrFlick    schedule 16.04.2015

Вы можете использовать mapvalues из пакета plyr, который переназначает указанный уровни фактора, оставляя другие нетронутыми:

my.factor <- function(data){
    levels = c("d1", "d2", "d3")
    labels = c("Data 1", "Data 2", "Data 3")
    plyr::mapvalues(factor(data), levels, labels)
}

my.factor(c("d1", "d2", "d3", "d100"))
person David Robinson    schedule 16.04.2015

использование %in% - это один из способов...

 my.factor <- function(data){
    levels = c("d1", "d2", "d3")
    labels = c("Data 1", "Data 2", "Data 3")
    extra <- data[!(data %in% levels)]
    if(length(extra) > 0){
    levels = c("d1", "d2", "d3", extra)
    labels = c("Data 1", "Data 2", "Data 3", extra)
    }
    factored.data = factor(data, levels, labels)
    factored.data
  }

data <- c("d1", "d2", "d3","d100")
my.factor(data)
#[1] Data 1 Data 2 Data 3 d100  
#Levels: Data 1 Data 2 Data 3 d100

data <- c("d1", "d2", "d3", "d1", "d100")
my.factor(data)
#[1] Data 1 Data 2 Data 3 Data 1 d100  
#Levels: Data 1 Data 2 Data 3 d100
person user1317221_G    schedule 16.04.2015