Главная страница

А. Б. Шипунов, Е. М. Балдин, П. А. Волкова, А. И. Коробейников, С. А. Назарова


Скачать 3.04 Mb.
НазваниеА. Б. Шипунов, Е. М. Балдин, П. А. Волкова, А. И. Коробейников, С. А. Назарова
Анкорrbook
Дата29.09.2022
Размер3.04 Mb.
Формат файлаpdf
Имя файлаrbook.pdf
ТипДокументы
#705644
страница16 из 19
1   ...   11   12   13   14   15   16   17   18   19
Так что если у вас есть навыки работы в Emacs, то ESS — это верный выбор. Но если вы предпочитаете другой редактор, то расстраиваться не стоит. Почти все «уважающие себя» текстовые редакторы или сре- ды разработки в той или иной степени поддерживают R. Кроме уже упомянутого Emacs, к таковым относятся и Vim, и jEdit, и Bluefish,
и SciTE. «Большие» IDE, например Eclipse и Komodo, тоже имеет со- ответствующие модули (соответственно, StatET, http://www.walware.
de/goto/statet
, и SciViews-K, http://www.sciviews.org/SciViews-K/
index.html
). Под Windows есть замечательный редактор Tinn-R.

Приложение В
Основы программирования в R
Это приложение — для «продвинутого» читателя, который уже име- ет определенный опыт программирования и хочет освоить азы програм- мирования в R.
В.1. Базовые объекты языка R
Любой объект языка R имеет набор атрибутов (attributes). Этот на- бор может быть разным для объектов разного вида, но каждый объект обязательно имеет два встроенных атрибута:
• длина (length);
• тип (mode).
Смысл атрибута «длина» достаточно очевиден. Тип объекта — более сложная сущность. Так например, тип объекта vector определяется типом элементов, из которых он состоит.
В.1.1. Вектор
Вектор является простейшим объектом, объединяющим элементы одного примитивного типа. Создать пустой вектор можно при помощи функции vector():
> v <- vector(mode = "logical", length = 0)
Здесь аргумент length задает длину вектора (то есть количество содержащихся в нем элементов), а mode — примитивный тип элементов.
Объекты примитивного типа numeric служат для представления обычных чисел с плавающей точкой. Отметим, что, кроме «обычных»
значений, объекты типа numeric могут принимать ряд специальных. Та- ковыми являются бесконечность Inf (которая, в свою очередь, может быть положительной или отрицательной) и NaN (Not-A-Number). По- следнее служит для отображения результатов операций в том случае,

Базовые объекты языка R
223
когда этот результат не определен (например, деление ноля на ноль,
вычитание из бесконечности и т. п.)
Еще одно специальное значение, NA (Not Available), служит для отоб- ражения «пропусков» в данных. Использование отдельного значения для пропущенных наблюдений позволяет решить универсальным обра- зом множество проблем при работе с реальными данными. Сразу же отметим, что значение NA могут принимать объекты любого примитив- ного типа.
Объекты типа complex содержат комплексные числа. Мнимая часть комплексного числа записывается с символом i на конце. Примером комплексного вектора длины 3 может служить
> c(5.0i, -1.3+8.73i, 2.0)
Комплексные векторы могут принимать те же специальные значе- ния, что и числовые.
Объекты типа logical могут принимать одно из трех значений: TRUE,
FALSE
и NA. Кроме этого, существуют (в основном в целях обратной совместимости) глобальные переменные T и F, имеющие значение TRUE
и FALSE соответственно.
Каждый элемент вектора типа character является, как следует из названия типа, строкой. Каждая такая строка может иметь произволь- ную длину.
Как и в языке C, символ обратной косой черты является специаль- ным и предназначен для ввода так называемых escape-последователь- ностей. В частности, обычный символ обратной косой черты (backslash)
вставляется при помощи последовательности «\\», символ табуляции —
при помощи «\t», а перехода на новую строку — при помощи «\n».
Строки заключаются в одинарные или двойные кавычки. В случае ис- пользования двойных кавычек любую двойную кавычку внутри строки необходимо предварять символом «\». Аналогично следует поступать с одинарными кавычками внутри строки, заключенной в одинарные ка- вычки. При выводе на экран всегда используются двойные кавычки.
Вместо вызова функции vector() с указанием типа элемента удобно вызывать функции, создающие объект нужного типа сразу:
> v1 <- numeric(length = 0)
> v2 <- character(length = 0)
> v3 <- complex(length = 0)
> v4 <- logical(length = 0)
В.1.2. Список
Вектор содержит элементы исключительно одного типа. Это делает его простым, но в то же время несколько ограничивает сферу его при-

224
Основы программирования в R
менения. В этом полной противоположностью вектору служит список.
Список является объектом типа list, его длина — это количество ком- понентов, из которых он состоит. Каждый компонент списка является произвольным объектом языка R.
Так, например, первый компонент списка может быть числовым век- тором длины 10, второй компонент — списком, а третий — строкой.
Пустой список можно получить вызовом функции vector():
> l <- vector(mode = "list", length = 3)
Список с одновременной инициализацией создается функцией list():
> l <- list(c(1, 5, 7), "string", c(TRUE, FALSE))
Отдельные компоненты списка могут иметь имя. Для его задания необходимо передать функции list() пары «имя=значение»:
> l <- list(A=c(1, 5, 7), "string", B=c(TRUE, FALSE))
Преобразовать список в вектор можно командой unlist(), а в мат- рицу — при помощи do.call() (см. ниже).
В.1.3. Матрица и многомерная матрица
Как было отмечено выше, каждый объект языка R обладает неко- торым набором атрибутов. Атрибуты — это список, каждый компонент которого имеет имя (именованный список). Матрицы являются хоро- шим примером применения атрибутов на практике. Так, матрица (мас- сив) фактически представляет собой просто вектор с дополнительным атрибутом dim и, опционально, атрибутом dimnames.
Атрибут dim представляет собой числовой вектор, длина которого равна размерности матрицы (таким образом, типичная двумерная мат- рица имеет атрибут dim длины 2). Элементы вектора dim показывают,
сколько строк, столбцов и т. д. содержится в матрице. Произведение всех элементов вектора dim должно совпадать с длиной объекта. Ат- рибут dimnames позволяет задать название для каждой размерности матрицы.
Многомерная матрица (многомерный массив) создается функцией array()
:
> a <- array(data = NA, dim = length(data), dimnames = NULL)
Здесь data — исходные данные для матрицы, dim, dimnames — зна- чения соответствующих атрибутов. Двумерная матрица (как наиболее часто используемый вид) может быть создана при помощи специальной функции matrix():

Базовые объекты языка R
225
> m <- matrix(data = NA, nrow = 1, ncol = 1, byrow = FALSE,
+ dimnames = NULL)
Здесь data — исходное содержимое матрицы, nrow, ncol — коли- чество строк и столбцов. Аргумент byrow позволяет задать, каким об- разом заполнять матрицу из вектора data: по столбцам (по умолчанию)
или по строкам. dimnames позволяет задать имена строк и столбцов.
Кроме этого, создать матрицу или многомерную матрицу можно прос- тым назначением атрибута dim вектору:
> v <- numeric(6)
> dim(v) <- c(2, 3); v
[,1] [,2] [,3]
[1,]
0 0
0
[2,]
0 0
0
В.1.4. Факторы
Объект типа factor является способом представления номинальных
(категориальных) и шкальных типов данных в R. Качественные данные принимают значения в некотором конечном множестве. Поэтому для задания подобных данных достаточно задать это множество (способ кодирования этих данных) — множество градаций, или уровней (levels),
фактора. Чаще всего для кодирования градаций берут обычные числа.
Создать фактор можно при помощи функции factor(data, levels,
labels=levels)
. Здесь data — отдельные значения, levels — вектор всех возможных значений для градаций, labels — опциональный век- тор, содержащий текстовые обозначения градаций, используемые при выводе фактора на экран. Задание дополнительно аргумента order поз- воляет получить упорядоченный фактор.
> f <- factor(c(1, 1, 2, 1, 3), levels = 1:5,
+ labels=c("A", "B", "C", "D", "E"))
> f
[1] A A B A C
Levels: A B C D E
> f <- factor(c(1, 1, 2, 1, 3), levels = 1:5,
+ labels = c("A", "B", "C", "D", "E"), ordered = TRUE)
f
[1] A A B A C
Levels: A < B < C < D < E

226
Основы программирования в R
В.1.5. Таблица данных
Матрицы и многомерные матрицы позволяют хранить элементы только одного типа и поэтому не очень хорошо приспособлены для ра- боты с реальными данными. Реальные данные, как правило, представ- ляют собой набор однотипных наблюдений. Каждое наблюдение, в свою очередь, есть совокупность элементов разного типа (например, для ме- дицинских данных характерно наличие поля «имя» строкового типа,
категориального поля «пол» и числового поля «возраст»).
Таким образом, помещая отдельные наблюдения в строки, прихо- дим к своеобразной матрице, таблице данных, в которой элементы в одном столбце должны обязательно иметь одинаковый тип, но этот тип может меняться от столбца к столбцу. В статистической литературе традиционно отдельное наблюдение называется индивидом, а столбец с данными — признаком.
С другой стороны, объект «таблица данных» (data frame) может рассматриваться как обычный список векторов одинаковой длины (соб- ственно, он таковым и является). Создать таблицу данных можно при помощи функции data.frame(..., row.names = NULL).
В качестве аргументов здесь передаются столбцы создаваемого на- бора данных либо в виде пар типа имя = значение, либо просто «как есть» (в таком случае столбец получит автоматически назначаемое имя
V1
, V2, ...). Аргумент row.names позволяет задать вектор с названиями для отдельных строк (конечно, его длина обязательно должна совпа- дать с длиной векторов данных, а сами имена не должны повторяться).
Отметим, что большинство объектов могут быть преобразованы в объект типа data.frame «естественным» образом, например:
> data.frame(matrix(1:6, nrow = 2, ncol = 3))
X1 X2 X3 1
1 3
5 2
2 4
6
В.1.6. Выражение
Язык R предоставляет доступ к конструкциям самого языка. Так,
функция, как будет описано далее, является объектом типа function,
причем его содержимое — это просто код функции. Поэтому с функция- ми можно в некотором смысле работать как с обыкновенными перемен- ными (переименовывать, передавать в качестве аргументов, сохранять в списки и т. д.)
Объект типа expression представляет собой еще не выполненное выражение языка R, то есть попросту строку или набор строк кода.

Операторы доступа к данным
227
Такие выражения можно выполнять или, в более общем случае, под- ставлять в них значения каких-либо переменных, преобразовывать и т. д. Создать выражение можно при помощи функции expression():
> e <- expression((x + y) / exp(z))
> x <- 1; y <- 2; z <- 0; eval(e)
[1] 3
Ее аргументом является выражение языка R. Вычислить выраже- ние можно при помощи функции eval(). По умолчанию переменные для подстановки берутся из текущего окружения. Это поведение можно переопределить, передав требуемое окружение через аргумент envir.
В качестве примера нетривиального преобразования выражений от- метим функцию символьного дифференцирования D(), первым аргу- ментом которой является выражение, которое необходимо дифферен- цировать, а вторым — название переменной дифференцирования:
> e <- expression((x + y) / exp(z))
> D(e, "x")
1/exp(z)
Результатом функции D() снова является объект типа expression.
В.2. Операторы доступа к данным
Все операции доступа к данным можно разделить на две категории:
извлечения и замены. В первом случае оператор доступа к данным сто- ит справа от оператора присваивания, во втором — слева:
value
<- x[sub]
# извлечение x[sub] <- value
# замена
Хотя дальнейшие примеры и будут, как правило, описаны в терми- нах операции извлечения, сразу же стоит отметить, что все нижеописан- ное применимо и к операции замены (если явно не сказано обратного).
В.2.1. Оператор
[ с положительным аргументом
Оператор «одинарная левая квадратная скобка» служит для извле- чения элементов с индексами, соответствующими элементам передан- ного вектора. Например, следующая конструкция извлечет из вектора v
первые 3 элемента:

228
Основы программирования в R
> v <- 1:5
> v[1:3]
[1] 1 2 3
Результат имеет ту же длину, что и вектор индексов. Никаких огра- ничений ни на длину, ни на содержимое вектора индексов нет (таким образом, любой индекс может встречаться произвольное число раз). Ин- дексы, равные NA, или имеющие значение больше, чем длина вектора,
приводят в результате к NA (или к пустым строкам).
В случае использования операции замены длина результата равна максимальному индексу. Элементы, значение которым не присвоено,
получают значение NA:
> v <- 1:5
> v[10] <- 10
> v
[1]
1 2
3 4
5 NA NA NA NA 10
В.2.2. Оператор
[ с отрицательным аргументом
В случае, когда вектор индексов содержит отрицательные значения,
результат содержит все элементы, кроме указанных. Например:
> v <- 1:5
> v[-c(1,5)]
[1] 2 3 4
Нулевые, повторяющиеся и индексы больше длины вектора игнори- руются. Пропущенные значения в индексах приводят к ошибке, равно как и смесь положительных и отрицательных индексов.
В.2.3. Оператор
[ со строковым аргументом
В качестве индекса можно использовать строку. В таком случае по- иск элементов идет не по номеру, а по имени.
> v <- 1:5
> names(v) <- c("first", "second", "third", "fourth", "fifth")
> v first second third fourth fifth
1 2
3 4
5
> v[c("first", "third")]
first third
1 3

Операторы доступа к данным
229
В.2.4. Оператор
[ с логическим аргументом
Типичным примером использования оператора [ с логическим век- тором в качестве аргумента является конструкция вида
> v[v < 0]
,
извлекающая из вектора v только отрицательные элементы. Пред- полагается, что длина аргумента совпадает с длиной вектора, в против- ном случае аргумент повторяется столько раз, сколько необходимо для достижения длины вектора. В результат попадают только те элементы вектора, элемент вектора индексов для которых совпадает с TRUE. Ин- декс NA выбирает элемент NA (с «никаким» индексом). Таким образом,
длина результата совпадает с общим количеством индексов TRUE и NA:
> v <- 1:50
> even <- c(FALSE, TRUE)
> v[even]
[1]
2 4
6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48 50
> three <- rep(c(FALSE, FALSE, TRUE), length = length(v))
> v[even & three]
[1]
6 12 18 24 30 36 42 48
Отметим, что в случае замены индексы NA допускаются, только если длина вектора, стоящего справа от оператора присваивания, равна 1 (в противном случае непонятно, следует ли использовать очередной эле- мент замещающего вектора или нет; при длине замещающего вектора
= 1
эта неоднозначность, очевидно, не влияет на результат):
v[c(TRUE, NA)] <- 1:50
Error in v[c(TRUE, NA)] <- 1:50 :
NAs are not allowed in subscripted assignments
> v[c(TRUE, NA)] <- 0
> v
[1]
0 2
0 4
0 6
0 8
0 10 0 12 0 14 0 16 0 18 0 20 0 22 0 24 0
[26] 26 0 28 0 30 0 32 0 34 0 36 0 38 0 40 0 42 0 44 0 46 0 48 0 50
В.2.5. Оператор
$
Оператор $ служит для извлечения отдельного элемента из списка.
Синтаксис очень прост: слева от знака $ стоит список, элемент которого следует извлечь, а справа — имя извлекаемого элемента:

230
Основы программирования в R
> .Machine$double.eps
[1] 2.220446e-16
Оператор $ обладает одной полезной особенностью: имя элемен- та нет необходимости передавать полным, достаточно лишь префикса,
определяющего нужный элемент однозначно.
> .Machine$double.ep
[1] 2.220446e-16
В случае, если элемент не определяется однозначно, будет возвра- щено значение NULL:
> names(.Machine)[grep("double.e", names(.Machine))]
[1] "double.eps"
"double.exponent"
> .Machine$double.e
NULL
Следует, однако, предельно осторожно обращаться с неполными име- нами при выполнении замены: произойдет добавление нового значения с коротким именем. Старое значение с полным именем останется неиз- менным:
> l <- list(abc=1:10)
> l
$abc
[1]
1 2
3 4
5 6
7 8
9 10
> l$a
[1]
1 2
3 4
5 6
7 8
9 10
> l$a <- 1:3
> l
$abc
[1]
1 2
3 4
5 6
7 8
9 10
$a
[1] 1 2 3
В.2.6. Оператор
[[
Вообще говоря, оператор $ может быть удален из языка без потери какой-либо функциональности. Оператор [[ позволяет осуществлять все те же операции и даже больше. Выражение типа .Machine$double.eps полностью эквивалентно .Machine[["double.eps"]]. Первое, правда,
короче на 5 символов и выглядит как единое целое.

Операторы доступа к данным
231
Оператор $ не может быть использован, если элемент списка не име- ет имени: доступ по индексу возможен только посредством оператора
[[
. Кроме этого, оператор [[ следует применять в том случае, когда интересующее нас имя элемента уже содержится в некоторой перемен- ной:
> l <- list(A=1:10)
> cname <- "A"
> l$cname
NULL
> l[[cname]]
[1]
1 2
3 4
5 6
7 8
9 10
Отметим также, что по умолчанию оператор [[ требует точного сов- падения переданного названия элемента. Это поведение можно пере- определить при помощи аргумента exact:
> l <- list(abc=1:10)
> l$a
[1]
1 2
3 4
5 6
7 8
9 10
> l[["a"]]
NULL
> l[["a", exact=FALSE]]
[1]
1 2
3 4
5 6
7 8
9 10
Необходимо всегда иметь в виду важный факт: разобранный ранее оператор [ работает не только с векторами, но и со списками. Отличие заключается в том, что оператор [[ всегда возвращает элемент списка,
а [ — список:
> .Machine[[1]]
[1] 2.220446e-16
> .Machine[1]
$double.eps
[1] 2.220446e-16
Кроме этого, аргумент оператора [[ всегда имеет длину 1, а аргу- мент оператора [ может быть вектором с семантикой, описанной выше.
В.2.7. Доступ к табличным данным
Табличные данные, организованные в матрицы или таблицы дан- ных, имеют свои правила доступа: каждое измерение может быть ин- дексировано независимо. Вектор индексов для каждого измерения мо-

232
Основы программирования в R
жет принимать любую из форм, допустимых для оператора [, как было описано выше (хотя векторы строк будут индексировать не имена эле- ментов, а имена измерений):
> state.x77[1:2, c("Area", "Population")]
Area Population
Alabama
50708 3615
Alaska
566432 365
В случае если одно (или больше) измерение результата будет иметь длину 1, то это измерение будет «схлопнуто»: так, ниже видно, что
1   ...   11   12   13   14   15   16   17   18   19


написать администратору сайта