Поиск…


Синтаксис

  1. фактор (x = символ (), уровни, метки = уровни, исключить = NA, упорядочено = is.ordered (x), nmax = NA)
  2. Запустить ?factor Или просмотреть документацию в Интернете.

замечания

Объектом с factor класса является вектор с определенным набором характеристик.

  1. Он хранится внутри как integer вектор.
  2. Он поддерживает атрибут levels показывает отображение символа значений.
  3. Его класс хранится как factor

Чтобы проиллюстрировать, создадим вектор 1000 наблюдений из набора цветов.

set.seed(1)
Color <- sample(x = c("Red", "Blue", "Green", "Yellow"), 
                size = 1000, 
                replace = TRUE)
Color <- factor(Color)

Мы можем наблюдать каждую из характеристик Color перечисленных выше:

#* 1. It is stored internally as an `integer` vector
typeof(Color)
[1] "integer"
#* 2. It maintains a `levels` attribute the shows the character representation of the values.
#* 3. Its class is stored as `factor`
attributes(Color)
$levels
[1] "Blue"   "Green"  "Red"    "Yellow"

$class
[1] "factor"

Основным преимуществом фактор-объекта является эффективность хранения данных. Целое число требует меньше памяти для хранения, чем символ. Такая эффективность была очень желательна, когда многие компьютеры имели гораздо более ограниченные ресурсы, чем текущие машины (для более подробной истории мотиваций, связанных с использованием факторов, см. stringsAsFactors : Unauthorized Biography ). Разницу в использовании памяти можно увидеть даже в нашем объекте Color . Как вы можете видеть, для сохранения Color в качестве символа требуется примерно в 1,7 раза больше памяти, чем фактор-объект.

#* Amount of memory required to store Color as a factor.
object.size(Color)
4624 bytes
#* Amount of memory required to store Color as a character
object.size(as.character(Color))
8232 bytes

Отображение целого числа до уровня

Хотя внутреннее вычисление факторов рассматривает объект как целое, желательным представлением для потребления человеком является уровень персонажа. Например,

head(Color)
[1] Blue   Blue   Green  Yellow Red    Yellow  
Levels: Blue Green Red Yellow

легче для понимания человеком, чем

head(as.numeric(Color))
[1] 1 1 2 4 3 4

Примерная иллюстрация того, как R идет о совпадении представления символа с внутренним целочисленным значением:

head(levels(Color)[as.numeric(Color)])
[1] "Blue"   "Blue"   "Green"  "Yellow" "Red"    "Yellow"

Сравните эти результаты с

head(Color)
[1] Blue   Blue   Green  Yellow Red    Yellow  
Levels: Blue Green Red Yellow

Современное использование факторов

В 2007 году R представил метод хэширования для символов, который уменьшил нагрузку на память векторных векторов (ref: stringsAsFactors : Unauthorized Biography ). Обратите внимание, что, когда мы определили, что персонажам требуется в 1,7 раза больше места для хранения, чем факторы, которые были рассчитаны в недавней версии R, это означает, что использование символьных векторов памяти было еще более подвержено налогообложению до 2007 года.

Благодаря методу хеширования в современном R и значительно большему ресурсу памяти в современных компьютерах проблема эффективности памяти при хранении символьных значений была сведена к очень малой проблеме. Преобладающая позиция в сообществе R - это предпочтение векторам символов над факторами в большинстве ситуаций. Основными причинами перехода от факторов являются

  1. Увеличение неструктурированных и / или слабо управляемых символьных данных
  2. Тенденция факторов не вести себя по желанию, когда пользователь забывает, что она имеет дело с фактором, а не с характером

В первом случае нет смысла хранить свободные текстовые или открытые поля ответа в качестве факторов, так как вряд ли будет какой-либо шаблон, который допускает более одного наблюдения за уровень. В качестве альтернативы, если структура данных не контролируется тщательно, можно получить несколько уровней, соответствующих одной и той же категории (например, «синий», «синий» и «ГОЛУБОЙ»). В таких случаях многие предпочитают управлять этими расхождениями как символы перед преобразованием в фактор (если конверсия вообще происходит).

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

Базовое создание факторов

Факторы - один из способов представления категориальных переменных в R. Фактор хранится внутри как вектор целых чисел . Уникальные элементы предоставленного символа вектора называются уровнями фактора. По умолчанию, если уровни не предоставляются пользователем, тогда R генерирует набор уникальных значений в векторе, сортирует эти значения буквенно-цифровым способом и использует их в качестве уровней.

 charvar <- rep(c("n", "c"), each = 3)
 f <- factor(charvar)
 f
 levels(f)

> f
[1] n n n c c c
Levels: c n
> levels(f)
[1] "c" "n"

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

levels(factor(charvar, levels = c("n","c")))

> levels(factor(charvar, levels = c("n","c")))
[1] "n" "c"

Факторы имеют ряд свойств. Например, уровням могут быть присвоены метки:

> f <- factor(charvar, levels=c("n", "c"), labels=c("Newt", "Capybara"))
> f
[1] Newt     Newt     Newt     Capybara Capybara Capybara
Levels: Newt Capybara

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

> Weekdays <- factor(c("Monday", "Wednesday", "Thursday", "Tuesday", "Friday", "Sunday", "Saturday"))
> Weekdays
[1] Monday    Wednesday Thursday  Tuesday   Friday    Sunday    Saturday 
Levels: Friday Monday Saturday Sunday Thursday Tuesday Wednesday
> Weekdays <- factor(Weekdays, levels=c("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"), ordered=TRUE)
> Weekdays
[1] Monday    Wednesday Thursday  Tuesday   Friday    Sunday    Saturday 
Levels: Monday < Tuesday < Wednesday < Thursday < Friday < Saturday < Sunday

Когда уровень фактора больше не используется, вы можете отказаться от него с помощью функции droplevels() :

> Weekend <- subset(Weekdays, Weekdays == "Saturday" |  Weekdays == "Sunday")
> Weekend
[1] Sunday   Saturday
Levels: Monday < Tuesday < Wednesday < Thursday < Friday < Saturday < Sunday
> Weekend <- droplevels(Weekend)
> Weekend
[1] Sunday   Saturday
Levels: Saturday < Sunday

Консолидация уровней факторов со списком

Бывают моменты, когда желательно объединить уровни факторов в меньшее количество групп, возможно, из-за редких данных в одной из категорий. Это может также произойти, когда у вас разные варианты написания или капитализация названий категорий. Рассмотрим в качестве примера фактор

set.seed(1)
colorful <- sample(c("red", "Red", "RED", "blue", "Blue", "BLUE", "green", "gren"),
                   size = 20,
                   replace = TRUE)
colorful <- factor(colorful)

Так как R чувствительна к регистру, таблица частот этого вектора будет выглядеть так, как показано ниже.

table(colorful)
colorful  
blue  Blue  BLUE green  gren   red   Red   RED  
   3     1     4     2     4     1     3     2

Однако эта таблица не отражает истинное распределение данных, и категории могут быть эффективно уменьшены до трех типов: синий, зеленый и красный. Приведены три примера. Первый иллюстрирует то, что кажется очевидным решением, но на самом деле не даст решения. Второе дает рабочее решение, но оно многословно и вычислительно дорого. Третий не является очевидным решением, но относительно компактен и эффективно вычисляется.

Консолидация уровней с использованием factor ( factor_approach )

factor(as.character(colorful),
       levels = c("blue", "Blue", "BLUE", "green", "gren", "red", "Red", "RED"),
       labels = c("Blue", "Blue", "Blue", "Green", "Green", "Red", "Red", "Red"))
 [1] Green Blue  Red   Red   Blue  Red   Red   Red   Blue  Red   Green Green Green Blue  Red   Green
[17] Red   Green Green Red  
Levels: Blue Blue Blue Green Green Red Red Red
Warning message:
In `levels<-`(`*tmp*`, value = if (nl == nL) as.character(labels) else paste0(labels,  :
  duplicated levels in factors are deprecated

Обратите внимание, что существуют дублированные уровни. У нас все еще есть три категории для «Синего», что не завершает нашу задачу консолидации уровней. Кроме того, существует предупреждение о том, что дублированные уровни устарели, что означает, что этот код может вызвать ошибку в будущем.

Консолидация уровней с использованием ifelse ( ifelse_approach )

factor(ifelse(colorful %in% c("blue", "Blue", "BLUE"),
       "Blue",
       ifelse(colorful %in% c("green", "gren"),
              "Green",
              "Red")))
 [1] Green Blue  Red   Red   Blue  Red   Red   Red   Blue  Red   Green Green Green Blue  Red   Green
[17] Red   Green Green Red  
Levels: Blue Green Red

Этот код генерирует желаемый результат, но требует использования вложенных операторов ifelse . Хотя в этом подходе нет ничего плохого, управление вложенными ifelse может быть утомительной задачей и должно быть сделано тщательно.

Консолидация уровней факторов со списком ( list_approach )

Менее очевидным способом консолидации уровней является использование списка, в котором имя каждого элемента является желаемым именем категории, а элемент является символьным вектором уровней в коэффициенте, который должен отображаться в нужной категории. Это имеет дополнительное преимущество, непосредственно работая над атрибутом levels фактора без необходимости назначать новые объекты.

levels(colorful) <- 
     list("Blue" = c("blue", "Blue", "BLUE"),
          "Green" = c("green", "gren"),
          "Red" = c("red", "Red", "RED"))
 [1] Green Blue  Red   Red   Blue  Red   Red   Red   Blue  Red   Green Green Green Blue  Red   Green
[17] Red   Green Green Red  
Levels: Blue Green Red

Бенчмаркинг каждого подхода

Время, необходимое для выполнения каждого из этих подходов, приводится ниже. (Для космоса код для создания этого резюме не показан)

Unit: microseconds
          expr     min      lq      mean   median      uq     max neval cld
        factor  78.725  83.256  93.26023  87.5030  97.131 218.899   100  b 
        ifelse 104.494 107.609 123.53793 113.4145 128.281 254.580   100   c
 list_approach  49.557  52.955  60.50756  54.9370  65.132 138.193   100 a

Подход к списку работает примерно в два раза быстрее, чем подход ifelse . Однако, за исключением очень больших объемов данных, различия во времени выполнения, вероятно, будут измеряться либо в микросекундах, либо в миллисекундах. При таких небольших временных различиях эффективность не должна определять решение о том, какой подход использовать. Вместо этого используйте знакомый и удобный подход, который вы и ваши сотрудники поймете в будущем обзоре.

факторы

Факторы - это один из способов представления категориальных переменных в R. Для вектора x , значения которого могут быть преобразованы в символы с использованием as.character() , аргументы по умолчанию для factor() и as.factor() присваивают целое число каждому отдельному элементу из вектор, а также атрибут уровня и атрибут метки. Уровни - это значения, которые могут принимать значения x и метки могут быть либо заданным элементом, либо определенным пользователем.

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

# standard
factor(c(1,1,2,2,3,3))
[1] 1 1 2 2 3 3
Levels: 1 2 3

Экземпляры могут возникать, когда пользователь знает количество возможных значений, которые может принимать фактор, больше текущих значений в векторе. Для этого мы сами присваиваем уровни в factor() .

factor(c(1,1,2,2,3,3),
         levels = c(1,2,3,4,5))
[1] 1 1 2 2 3 3
Levels: 1 2 3 4 5

В целях стиля пользователь может пожелать присвоить метки каждому уровню. По умолчанию метки являются символьным представлением уровней. Здесь мы назначаем метки для каждого из возможных уровней фактора.

factor(c(1,1,2,2,3,3),
       levels = c(1,2,3,4,5),
       labels = c("Fox","Dog","Cow","Brick","Dolphin"))
[1] Fox Fox Dog Dog Cow Cow
Levels: Fox Dog Cow Brick Dolphin

Обычно коэффициенты можно сравнивать только с помощью == и != И если коэффициенты имеют одинаковые уровни. Следующее сравнение факторов не удается, хотя они выглядят одинаковыми, поскольку факторы имеют разные уровни факторов.

factor(c(1,1,2,2,3,3),levels = c(1,2,3)) == factor(c(1,1,2,2,3,3),levels = c(1,2,3,4,5))
Error in Ops.factor(factor(c(1, 1, 2, 2, 3, 3), levels = c(1, 2, 3)),  : 
  level sets of factors are different

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

Операторы < , <= , > и >= применимы только для упорядоченных множителей. Они могут представлять собой категориальные значения, которые все еще имеют линейный порядок. Упорядоченный множитель может быть создан путем предоставления ordered = TRUE аргумента ordered = TRUE factor функции или просто использования ordered функции.

x <- factor(1:3, labels = c('low', 'medium', 'high'), ordered = TRUE)
print(x)
[1] low    medium high  
Levels: low < medium < high

y <- ordered(3:1, labels = c('low', 'medium', 'high'))
print(y)
[1] high   medium low   
Levels: low < medium < high

x < y
[1]  TRUE FALSE FALSE

Для получения дополнительной информации см. Документацию Factor .

Изменение и изменение порядка

Когда факторы создаются со значениями по умолчанию, levels формируются с помощью as.character применяемого к входам, и упорядочиваются по алфавиту.

charvar <- rep(c("W", "n", "c"), times=c(17,20,14))
f <- factor(charvar)
levels(f)
# [1] "c" "n" "W"

В некоторых ситуациях обработка по умолчанию порядка levels (буквенно-лексический порядок) будет приемлемой. Например, если кто-то хочет plot частоту, это будет результат:

plot(f,col=1:length(levels(f)))

введите описание изображения здесь

Но если нам нужен другой порядок levels , мы должны указать это в параметрах levels или labels (учитывая, что значение «порядок» здесь отличается от упорядоченных факторов, см. Ниже). Существует много альтернатив для выполнения этой задачи в зависимости от ситуации.

1. Пересмотреть фактор

Когда это возможно, мы можем воссоздать коэффициент, используя параметр levels с нужным нам порядком.

ff <- factor(charvar, levels = c("n", "W", "c"))
levels(ff)
# [1] "n" "W" "c"
 
gg <- factor(charvar, levels = c("W", "c", "n"))
levels(gg)
# [1] "W" "c" "n"

Когда уровни ввода отличаются от желаемых уровней выходного сигнала, мы используем параметр labels который заставляет параметр levels становиться «фильтром» для допустимых входных значений, но оставляет конечные значения «уровней» для вектора факторов как аргумент labels :

fm <- factor(as.numeric(f),levels = c(2,3,1),
             labels = c("nn", "WW", "cc"))
levels(fm)
# [1] "nn" "WW" "cc"

fm <- factor(LETTERS[1:6], levels = LETTERS[1:4],  # only 'A'-'D' as input
                 labels = letters[1:4])            # but assigned to 'a'-'d'
fm
#[1] a    b    c    d    <NA> <NA>
#Levels: a b c d

2. Используйте функцию relevel

Когда есть один конкретный level который должен быть первым, мы можем использовать relevel . Это происходит, например, в контексте статистического анализа, когда base категория необходима для проверки гипотезы.

g<-relevel(f, "n") # moves n to be the first level
levels(g)
# [1] "n" "c" "W"  

Как можно проверить, f и g одинаковы

all.equal(f, g)
# [1] "Attributes: < Component “levels”: 2 string mismatches >"
all.equal(f, g, check.attributes = F)
# [1] TRUE

3. Переупорядочивающие факторы

Бывают случаи, когда нам необходимо reorder levels на основе числа, частичного результата, вычисленной статистики или предыдущих вычислений. Давайте переупорядочиваем, основываясь на частотах levels

table(g)
# g
#  n  c  W 
# 20 14 17 

Функция reorder является общей (см. help(reorder) ), но в этом контексте необходимо: x , в данном случае фактор; X , числовое значение той же длины, что и x ; и FUN - функция, которая должна применяться к X и вычисляется по уровню x , который определяет порядок levels , по умолчанию увеличивается. Результат - тот же самый фактор, что и его уровни переупорядочены.

g.ord <- reorder(g,rep(1,length(g)), FUN=sum) #increasing
levels(g.ord)
# [1] "c" "W" "n"

Чтобы получить убывающий порядок, рассмотрим отрицательные значения ( -1 )

g.ord.d <- reorder(g,rep(-1,length(g)), FUN=sum)
levels(g.ord.d)
# [1] "n" "W" "c"

Опять фактор тот же, что и другие.

data.frame(f,g,g.ord,g.ord.d)[seq(1,length(g),by=5),] #just same lines
#    f g g.ord g.ord.d
# 1  W W     W       W
# 6  W W     W       W
# 11 W W     W       W
# 16 W W     W       W
# 21 n n     n       n
# 26 n n     n       n
# 31 n n     n       n
# 36 n n     n       n
# 41 c c     c       c
# 46 c c     c       c
# 51 c c     c       c

Когда есть количественная переменная, связанная с факторной переменной, мы могли бы использовать другие функции для изменения порядка levels . Давайте возьмем данные iris ( help("iris") для получения дополнительной информации), для переупорядочения коэффициента Species , используя его средний Sepal.Width .

miris <- iris  #help("iris") # copy the data
with(miris, tapply(Sepal.Width,Species,mean))
#    setosa versicolor  virginica 
#     3.428      2.770      2.974 

miris$Species.o<-with(miris,reorder(Species,-Sepal.Width))
levels(miris$Species.o)
# [1] "setosa"     "virginica"  "versicolor"

Обычная boxplot (скажем: with(miris, boxplot(Petal.Width~Species) ) покажет especies в этом порядке: setosa , versicolor и virginica . Но используя упорядоченный множитель, мы получаем вид, упорядоченный по его среднему Sepal.Width :

boxplot(Petal.Width~Species.o, data = miris,
        xlab = "Species", ylab = "Petal Width",
        main = "Iris Data, ordered by mean sepal width", varwidth = TRUE,
        col = 2:4) 

введите описание изображения здесь

Кроме того, можно также изменить названия levels , объединить их в группы или добавить новые levels . Для этого мы используем функцию одноименных levels .

f1<-f
levels(f1)
# [1] "c" "n" "W"
levels(f1) <- c("upper","upper","CAP") #rename and grouping
levels(f1)
# [1] "upper" "CAP" 

f2<-f1
levels(f2) <- c("upper","CAP", "Number") #add Number level, which is empty
levels(f2)
# [1] "upper"  "CAP"    "Number"
f2[length(f2):(length(f2)+5)]<-"Number" # add cases for the new level
table(f2)
# f2
#  upper    CAP Number 
#     33     17      6 

f3<-f1
levels(f3) <- list(G1 = "upper", G2 = "CAP", G3 = "Number") # The same using list
levels(f3)
# [1] "G1" "G2" "G3"
f3[length(f3):(length(f3)+6)]<-"G3" ## add cases for the new level
table(f3)
# f3
# G1 G2 G3 
# 33 17  7 

- Упорядоченные факторы

Наконец, мы знаем, что ordered факторы отличаются от factors , первый из которых используется для представления порядковых данных , а второй - для работы с номинальными данными . Во-первых, не имеет смысла изменять порядок levels для упорядоченных факторов, но мы можем изменить его labels .

ordvar<-rep(c("Low", "Medium", "High"), times=c(7,2,4))

of<-ordered(ordvar,levels=c("Low", "Medium", "High"))
levels(of)
# [1] "Low"    "Medium" "High" 

of1<-of
levels(of1)<- c("LOW", "MEDIUM", "HIGH")
levels(of1)
# [1] "LOW"    "MEDIUM" "HIGH"
is.ordered(of1)
# [1] TRUE
of1
# [1] LOW    LOW    LOW    LOW    LOW    LOW    LOW    MEDIUM MEDIUM HIGH   HIGH   HIGH   HIGH  
# Levels: LOW < MEDIUM < HIGH

Восстановление факторов от нуля

проблема

Факторы используются для представления переменных, которые принимают значения из набора категорий, известных как Уровни в R. Например, некоторый эксперимент может характеризоваться уровнем энергии батареи с четырьмя уровнями: пустым, низким, нормальным и полным. Затем для 5 различных участков отбора проб эти уровни можно было бы определить в этих терминах следующим образом:

полный , полный , нормальный , пустой , низкий

Как правило, в базах данных или других источниках информации обработка этих данных осуществляется с помощью произвольных целочисленных индексов, связанных с категориями или уровнями. Если мы предположим, что для данного примера мы будем присваивать индексы следующим образом: 1 = пустое, 2 = низкое, 3 = нормальное, 4 = полное, тогда 5 выборок могут быть закодированы как:

4 , 4 , 3 , 1 , 2

Может случиться так, что из вашего источника информации, например базы данных, у вас есть только кодированный список целых чисел и каталог, связывающий каждое целое число с каждым ключевым словом. Как можно восстановить фактор R из этой информации?

Решение

Мы будем моделировать вектор из 20 целых чисел, который представляет образцы, каждый из которых может иметь одно из четырех значений:

set.seed(18)
ii <- sample(1:4, 20, replace=T)
ii

[1] 4 3 4 1 1 3 2 3 2 1 3 4 1 2 4 1 3 1 4 1

Первый шаг - сделать из предыдущей последовательности коэффициент, в котором уровни или категории - это точно числа от 1 до 4.

fii <- factor(ii, levels=1:4) # it is necessary to indicate the numeric levels
fii

[1] 4 3 4 1 1 3 2 3 2 1 3 4 1 2 4 1 3 1 4 1
Уровни: 1 2 3 4

Теперь просто, вы должны одеть фактор, уже созданный с помощью индексных тегов:

levels(fii) <- c("empty", "low", "normal", "full")
fii

[1] полный нормальный полный пустой пустой нормальный низкий нормальный низкий пустой
[11] нормальный полный пустой низкий полный пустой нормальный пустой полный пустой
Уровни: пустой низкий нормальный полный



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow