Объекты и типы данных языка R. Часть 2
Ришат Габидуллин — Пт, 09.09.2011
Факторы
Фактор – это специальный тип объектов, предназначенный для работы с категориальными или порядковыми данными. Категориальные данные, или данные измеренные в номинальной шкале, не имеют количественного выражения. Примером таких значений могут быть названия городов или имена людей. Порядковые переменные отличаются от категориальных тем, что позволяют упорядочивать объекты. Типичный пример порядковой или ординальной переменной – уровень доходов человека: низкий, средний, высокий. Очевидно, что низкий ниже среднего, а средний ниже высокого. Однако величину различий порядковая шкала измерений, как и номинальная, установить не позволяет.
Объект класса factor можно получить из числового или строкового вектора с помощью функции factor(). Следует иметь в виду, что числовые векторы данная функция преобразует в строку, поэтому выполнение каких-либо арифметических действий с факторами полученными из чисел невозможно, что соответствует требованиям к данным, выраженным в качественной шкале измерений.
Может показаться, что факторы – это излишество, поскольку в R уже есть тип строковых данных character. Тем не менее, это не так. Объекты данного класса позволяют эффективно использовать категориальные и порядковые переменные. В отличие от строковых векторов, эти объекты имеют два аттрибута: levels и class. Аттрибут class содержит название класса factor, а levels – уровни фактора. Уровни фактора – это все уникальные значения переменной.
Рссмотрим пример работы с факторами. Для начала создадим строковый вектор, содержащий обозначения двух цветов: пять эелементов "white" и шесть элементов "black".
> color <- rep(c("white", "black"), c(5, 6))
color
[1] "white" "white" "white" "white" "white" "black" "black" "black" "black"
[10] "black" "black"
> is.character(color)
[1] TRUE
> is.vector(color)
[1] TRUE
> is.factor(color)
[1] FALSE
> attributes(color)
NULL
Функция is.factor() показала, что color не является фактором. Это обычный символьный вектор без атрибутов. После преобразования переменной получим объект color.f класса factor.
> color.f <- factor(color)
> color.f
[1] white white white white white black black black black black black
Levels: black white
> is.factor(color.f)
[1] TRUE
При выводе на экран переменной color.f мы получаем список уровней данного фактора. Для того, чтобы узнать сколько раз встречается каждый уровень используется summary().
> summary(color.f)
black white
6 5
Еще один способ получить информацию по уровням – использование функции levels().
> levels(color.f)
[1] "black" "white"
В некоторых случаях факторы необходимо упорядочивать. Например, градация уровней доходов населения предусматривает определенную последовательность: от низких доходов к высоким. По умолчанию, уровни фактора сортируются в алфавитном порядке. Рассмотрим пример.
> earn <- c("low", "middle", "low", "low", "low", "low", "middle", "low", "middle", "middle", "middle", "middle", "middle", "high", "high", "low", "middle", "middle", "low", "high")
> earn.f.bad.order <- factor(earn)
> levels(earn.f.bad.order)
[1] "high" "low" "middle"
Как видите, последовательность уровней фактора в данном случае нелогична. Для того, чтобы исправить ситуацию можно задать произвольную последовательность уровней.
> earn.f <- factor(earn, levels = c("low", "middle", "high"))
> levels(earn.f)
[1] "low" "middle" "high"
Однако такая переменная все еще относится к разряду номинальных. Это значит, что мы не можем проводить операции сравнения с элементами данного объекта.
> earn.f[1]<earn.f[2]
[1] NA
Предупреждение
In Ops.factor(earn.f[1], earn.f[2]) : < не значимо для факторов
На данном этапе мы всего лишь изменили принцип сортировки с алфавитного на тот, который кажется более приемлемым. Чтобы переменная earn.f стала ординальной, необходимо упорядочить уровни фактора.
> earn.f.ordered <- factor(earn, levels = c("low", "middle", "high"), ordered=TRUE)
> earn.f.ordered
[1] low middle low low low low middle low middle middle
[11] middle middle middle high high low middle middle low high
Levels: low < middle < high
> earn.f.ordered[1]<earn.f.ordered[2]
[1] TRUE
Следует сказать, что добавление к фактору нового элемента, не входящего в подмножества его уровней невозможно. Попробуем добавить значение very.high в переменную earn.f.
> length(earn.f)
[1] 20
> earn.f[21] <- "very.high"
Предупреждение
In `[<-.factor`(`*tmp*`, 21, value = "very.high") :
invalid factor level, NAs generated
> earn.f
[1] low middle low low low low middle low middle middle
[11] middle middle middle high high low middle middle low high
[21] <NA>
Levels: low middle high
Как видите, вместо very.high мы получили NA. Дело в том, что в переменную-фактор можно добавить только такой элемент, который относится к одному из имеющихся уровней. Следовательно, для добавления элемента very.high, необходимо создать уровень фактора с таким названием.
> earn.f <- factor(earn.f, levels=c(levels(earn.f), "very.high"))
> earn.f[21] <- "very.high"
> earn.f
[1] low middle low low low low middle
[8] low middle middle middle middle middle high
[15] high low middle middle low high very.high
Levels: low middle high very.high
Следует сказать, что даже после удаления всех элементов одного типа из фактора количество его уровней остается прежним.
> earn.f.trunc <- earn.f[1:5]
> earn.f.trunc
[1] low middle low low low
Levels: low middle high very.high
Удаление лишних уровней происходит при использовании специального аргумента.
> earn.f.trunc <- earn.f[1:5, drop=TRUE]
> earn.f.trunc
[1] low middle low low low
Levels: low middle
Списки
Список (list) – это класс, позволяющий хранить в одной переменной объекты одного или разных типов, в том числе и другие списки. Объекты, входящие в список, могут быть не только разных типов, но и разного размера.
Создадим переменную-список.
> lst <- list(colors=c("red", "green", "blue"), hours=1:24, c(TRUE, FALSE, FALSE))
> lst
$colors
[1] "red" "green" "blue"
$hours
[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24[[3]]
[1] TRUE FALSE FALSE
Обращение к элементам списка возможно по их индексам или именам, если такие есть. Для указания индекса используются квадратные скобки. Каждый элемент извлеченный из списка таким образом, сам является списком.
> class(lst)
[1] "list"
> class(lst[1])
[1] "list"
> lst[1]
$colors
[1] "red" "green" "blue"
Если использовать двойные квадратные скобки, то тип полученного объекта будет соответствовать содержащимся в нем данным.
> lst[[1]]
[1] "red" "green" "blue"
> class(lst[[1]])
[1] "character"
Можно сказать, что с помощью двойных скобок мы выделяем из списка его элемент в «чистом виде». В представленном примере это символьный вектор.
Как уже было сказано, список позволяет хранить в себе разнородные данные. А для того, чтобы работать с ними было проще, каждому элементу списка можно задать имя (имена элементов списка не могут повторяться). Такой способ позволяет лучше ориентироваться в списке, особенно если он состоит из большого числа компонентов.
> names(lst)
[1] "colors" "hours" ""
В списке lst содержатся три элемента. Первым двум присвоены имена colors и hours, а последний не имеет имени, поэтому обращаться к нему можно только используя его порядковый номер в списке. Для вызова элементов списка по именам используются квадратные скобки или знак доллара ($). Следует отметить, что при использовании «[[]]» и «$» будут получены идентичные объекты одного класса.
> lst["colors"]
$colors
[1] "red" "green" "blue"
> class(lst["colors"])
[1] "list"
> lst[["colors"]]
[1] "red" "green" "blue"
> class(lst[["colors"]])
[1] "character"
> lst$colors
[1] "red" "green" "blue"
> class(lst$colors)
[1] "character"
Интересно, что имена элементов списка можно сокращать. Единственное требование к минимальному числу символов в сокращении – это возможность точной идентификации искомого элемента списка. В нашем примере использование одной только первой буквы позволит отличить один элемент списка от другого.
> lst$c
[1] "red" "green" "blue"
> lst$h
[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
Используя индексы в квадратных скобках можно добавлять новые элементы в список.
> lst[4] <- list(LETTERS)
> lst
$colors
[1] "red" "green" "blue"
$hours
[1] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
[[3]]
[1] TRUE FALSE FALSE
[[4]]
[1] "A" "B" "C" "D" "E" "F" "G" "H" "I" "J" "K" "L" "M" "N" "O" "P" "Q" "R" "S"
[20] "T" "U" "V" "W" "X" "Y" "Z"
Списки можно объединять также как и векторы. Для примера создадим два новых списка и объединим их.
> lst1 <- list(name=c("Fry", "Farnsworth"), age = c(35, 160))
> lst1
$name
[1] "Fry" "Farnsworth" $age
[1] 35 160
> lst2 <- list(job = c("delivery.boy", "scientist"), born = c(1975, 2841))
> lst2
$job
[1] "delivery.boy" "scientist"
$born
[1] 1975 2841
> LST <- c(lst1, lst2)
> LST
$name
[1] "Fry" "Farnsworth"
$age
[1] 35 160
$job
[1] "delivery.boy" "scientist"
$born
[1] 1975 2841
Таблицы данных
Таблица данных (data.frame) – класс позволяющий представлять данные в табличном виде. Таблица представляет собой набор векторов одинаковой длины, где каждый вектор – это столбец таблицы. Столбцы могут содержать данные разных типов, но в пределах одного столбца допустимы только однотипные значения. По сути, таблица данных – это модифицированный список, в котором каждый элемент представлен в виде столбца таблицы, и все элементы одинаковой длины. Рассмотрим созданную выше переменную LST.
> class(LST)
[1] "list"
> TBL <- as.data.frame(LST)
> class(TBL)
[1] "data.frame"
> TBL
name age job born
1 Fry 35 delivery.boy 1975
2 Farnsworth 160 scientist 2841
Посмотрим, какими атрибутами обладает объект класса data.frame.
> attributes(TBL)
$names
[1] "name" "age" "job" "born"
$row.names
[1] 1 2
$class
[1] "data.frame"
Как видите, кроме названия класса, у объекта имеются имена столбцов и строк. Имена строк могут выражены не только порядковыми номерами, но и произвольными строками. А имена столбцов являются названиями элементов списка.
Применим функцию unclass(), которая отключает все эффекты класса. В результате получим объект-список.
> uTBL <- unclass(TBL)
> uTBL
$name
[1] Fry Farnsworth
Levels: Farnsworth Fry
$age
[1] 35 160
$job
[1] delivery.boy scientist
Levels: delivery.boy scientist
$born
[1] 1975 2841
attr(,"row.names")
[1] 1 2
> class(uTBL)
[1] "list"
Обратите внимание, что элементы списка, содержащие строковые данные, при формировании таблицы были преобразованы в факторы.
> TBL$job
[1] delivery.boy scientist
Levels: delivery.boy scientist
> class(TBL$job)
[1] "factor"
> class(uTBL$job)
[1] "factor"
Как видно из примера, к таблице можно применить такие же методы индексации, как и к спискам. Кроме того, допустимо индексировать таблицы как двумерные матрицы. В квадратных скобках на первом месте указывается номер строки, а на втором – номер столбца.
> TBL[1, 2]
[1] 35
Для удаления определенного столбца или строки можно использовать отрицательную индексацию. Для примера уберем первую строку.
> TBL[-1, ]
name age job born
2 Farnsworth 160 scientist 2841
Для присоединения к таблице нового столбца или строки используются функции cbind() и rbind() соответственно.
> cbind(TBL, sex=c("male", "male"))
name age job born sex
1 Fry 35 delivery.boy 1975 male
2 Farnsworth 160 scientist 2841 male
Иногда приходится иметь дело с большими объемами данных. Выводить всю таблицу на экран для того чтобы ознакомиться с ее структурой в этом случае неудобно. Проблема решается функцией head(), которая выводит на экран только заголовки и первые строки таблицы.
Возмем переменную airquality, содержащую информацию о состоянии атмосферы в Нью-Йорке с мая по сентябрь 1973 года. Данная таблица входит в состав стандртной установки системы R.
> head(airquality)
Ozone Solar.R Wind Temp Month Day
1 41 190 7.4 67 5 1
2 36 118 8.0 72 5 2
3 12 149 12.6 74 5 3
4 18 313 11.5 62 5 4
5 NA NA 14.3 56 5 5
6 28 NA 14.9 66 5 6
Существует похожая функция tail(), которая выводит несколько последних строк таблицы.
> tail(airquality)
Ozone Solar.R Wind Temp Month Day
148 14 20 16.6 63 9 25
149 30 193 6.9 70 9 26
150 NA 145 13.2 77 9 27
151 14 191 14.3 75 9 28
152 18 131 8.0 76 9 29
153 20 223 11.5 68 9 30
Функции
В языке R функции – это объекты, принадлежащие классу function. Создавая собственные функции пользователь может значительно облегчить свою работу. Следует отметить, что большинство функций, используемых в языке R на нем же и написаны.
Создадим простейшую функцию для перевода температуры из шкалы Цельсия в шкалу Фаренгейта.
> Farenheit <- function(celsus) {
+ F <- celsus*9/5+32
+ F
+ }
> Farenheit(0)
[1] 32
> class(Farenheit)
[1] "function"
При создании функции в скобках указываются аргументы с которыми производятся вычисления, заданные в теле функции. Для того, чтобы вывести на экран тело функции, достаточно написать ее имя без скобок.
> Farenheit
function(celsus) {
F <- celsus*9/5+32
F
}
Понравилась статья? .

