R Language
факторы
Поиск…
Синтаксис
- фактор (x = символ (), уровни, метки = уровни, исключить = NA, упорядочено = is.ordered (x), nmax = NA)
- Запустить
?factor
Или просмотреть документацию в Интернете.
замечания
Объектом с factor
класса является вектор с определенным набором характеристик.
- Он хранится внутри как
integer
вектор. - Он поддерживает атрибут
levels
показывает отображение символа значений. - Его класс хранится как
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 - это предпочтение векторам символов над факторами в большинстве ситуаций. Основными причинами перехода от факторов являются
- Увеличение неструктурированных и / или слабо управляемых символьных данных
- Тенденция факторов не вести себя по желанию, когда пользователь забывает, что она имеет дело с фактором, а не с характером
В первом случае нет смысла хранить свободные текстовые или открытые поля ответа в качестве факторов, так как вряд ли будет какой-либо шаблон, который допускает более одного наблюдения за уровень. В качестве альтернативы, если структура данных не контролируется тщательно, можно получить несколько уровней, соответствующих одной и той же категории (например, «синий», «синий» и «ГОЛУБОЙ»). В таких случаях многие предпочитают управлять этими расхождениями как символы перед преобразованием в фактор (если конверсия вообще происходит).
Во втором случае, если пользователь считает, что она работает с символьным вектором, некоторые методы могут не реагировать так, как ожидалось. Это базовое понимание может привести к путанице и разочарованию при попытке отладки сценариев и кодов. Хотя, строго говоря, это может считаться ошибкой пользователя, большинство пользователей с радостью избегают использования факторов и вообще избегают этих ситуаций.
Базовое создание факторов
Факторы - один из способов представления категориальных переменных в 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] нормальный полный пустой низкий полный пустой нормальный пустой полный пустой
Уровни: пустой низкий нормальный полный