Sine of x x y Рис. 1.2. График синуса задать rgb-вектор функцией rgb(r, g, b). Параметры этой функции — значения от 0 до 1. • lty = стиль-линии определяет стиль линии; возможны значения "blank" (нет линии), "solid", "dashed", "dotted", "dotdash", "longdash", "twodash". Рассмотрим следующий пример: > plot(x, y, type = "l", col = "blue", main = "Sine of x") Следующие функции (называемые низкоуровневыми) никогда не стирают имеющегося изображения. Им могут быть переданы также дополнительные параметры, аналогичные соответствующим параметрам функции plot. points(x, y) рисует дополнительные точки, lines(x, y) рисует ломаную линию, соединяющую указанные точки. Этим функциям могут быть переданы дополнительные аргументы, например, type = тип-графика (по умолчанию он равен "p" для points и "l" для lines). text(x, y, текст) добавляет текст. По умолчанию он центрируется во- круг точки x, y. Указанные параметры могут быть векторами. В этом случае будет размещено несколько надписей. Можно указать шрифт font = шрифт и др. 12 > plot(x, y, type = "l", col = "blue", main = "Sine of x") Следующие функции (называемые низкоуровневыми) никогда ог не стирают имеющегося изображения. lty lines(x, y) text(x, y, текст)
abline(k, b) рисует прямую y=kx + b. Можно указать цвет и стиль ли- ниии и т. д. abline(h = y) abline(v = x) — для отрисовки горизонтальных и верти- кальных прямых. Указывается соответственно координата y и x. polygon(x, y) рисует многоугольник с вершинами x, y. Можно указать цвет заполнения col = цвет и цвет границы border = цвет. legend(x, y, легенда) добавляет легенду в указанную точку. Рассмотрим пример > t = seq(0, 10, by = 0.1) > y1 = 1.03*exp(-0.25*t)*sin(0.97*t) > y2 = 1.07*exp(-0.35*t)*sin(0.94*t) > y3 = 1.15*exp(-0.5*t)*sin(0.87*t) > y4 = 0.45*(exp(-0.38*t) - exp(-2.62*t)) > y5 = 0.22*(exp(-0.21*t) - exp(-4.80*t)) > plot(t, y1, type = "n", main = "Oscillation") > colors = c("blue", "red", "green", "cyan", "magenta") > lines(t, y1, col = colors[1]) > lines(t, y2, col = colors[2]) > lines(t, y3, col = colors[3]) > lines(t, y4, col = colors[4]) > lines(t, y5, col = colors[5]) > legends = paste("y", 1:5, sep = "") > legend(6, 0.6, legends, lty = "solid", col = colors) > abline(h = 0) # Горизонтальная ось > abline(v = 0) # Вертикальная ось Результат приведен на рис. 1.3 1.9. Специальная графика Функция barplot(x) рисует столбцовую диаграмму. При этом каждой компоненте вектора x будет соответствовать столбец. Если компоненты векто- ра x имеют имена, то они будут использоваться в качестве подписей к столб- цам диаграммы. Задать подписи можно с помощью дополнительного пара- метра names.arg = names. Определить цвет диаграммы можно с помощью дополнительного параметра col = colors. Здесь colors — либо число или строка, обозначающие цвет, которым будет нарисована диаграмма, либо век- тор, каждая компонента которого определяет цвет каждого столбца. Рассмотрим пример > area <- c(17075200, 9976140, 9639810, 9598077, 8511965, 7741220) > names(area) <- c("Russia", "Canada", "USA", "China", "Brazil", "Australia") > barplot(area, main = "Area", col = c("red", "green3", "brown3", "yellow", "blue", "green")) 13 abline(k, b) abline(h = y) abline(v = x) polygon(x, y) legend(x, y, легенда) barplot(x) names.arg col
0 2 4 6 8 10 −0.2 0.0 0.2 0.4 0.6 Oscillation t y1 y1 y2 y3 y4 y5 Рис. 1.3. Несколько графиков в одном графическом окне Результат представлен на рис. 1.4. Теперь рассмотрим случай, когда аргумент A функции barplot(A) — мат- рица. В этом случае каждому ее столбцу соответствует столбец диаграммы, составленный из маленьких столбиков, поставленных друг на друга. Высоты столбиков определяются соответствующими значениями, хранящимися в A. Если указано значение параметра beside = TRUE (по умолчанию beside = FALSE), то столбики будут поставлены не друг на друга, а рядом. Значение legend.text = TRUE включает отображение легенды. В качестве подписей к легенде берутся имена строк матрицы A. Также эти подписи можно указать явно, задав в качестве значения параметра legend.text = TRUE символьный массив. Рассмотрим пример > data = c( 12416505, 13130000, 12626921, 13060000, 8814860, 10170000, 3995077, 4218000, 3779044, 4156000, 1552008, 1746000, 1566253, 1655000) 14 beside legend.text
Russia Canada USA China Brazil Australia Area0.0e+00 5.0e+06 1.0e+07 1.5e+07 Рис. 1.4. Столбцовая диаграмма > gdp <- matrix(data, nrow = 2) > colnames(gdp) <- c( "USA", "EU", "China", "Japan", "India", "Russia", "Brazil") > rownames(gdp) <- c(2005, 2006) > barplot(gdp, beside = TRUE, col = 1:2, main = "GDP", legend.text = TRUE) Результат представлен на рис. 1.5. Функция pie(x) строит круговую диаграмму. Использование этой функ- ции аналогично использованию функции barplot, однако допустим только вариант, когда x — вектор (не матрица). Рассмотрим пример: > big.islands <- islands[islands < islands["Australia"] & islands >= islands["Sumatra"]] > big.islands > pie(sort(big.islands, decreasing = TRUE), col = 1:length(big.islands)) Результат представлен на рис. 1.6. Функция hist строит гистограмму. Количество отрезков, на которое раз- бивается интервал, выбирается автоматически, но можно его указать явно, 15 matrix(data, nrow = 2) rownames(gdp) colnames(gdp) pie(x) hist USA EU China Japan India Russia Brazil 2005 2006 GDP 0.0e+00 4.0e+06 8.0e+06 1.2e+07 Рис. 1.5. Столбцовая диаграмма определив значение параметра breaks. > set.seed(0) > x <- rnorm(200) > hist(x, breaks = 14, col = "cyan") Результат приведен на рис. 1.7. 1.10. Списки Списки в R — это коллекции объектов, доступ к котором можно проиво- дить по номеру или имени. Список может содержать объекты (компоненты) разных типов, что отличает списки от векторов. Компонентами списка могут быть в том числе векторы и другие списки. Функция > list(объект1, объект2, ...) создает список, содержащий указанные объекты. Например, > Euler = list("Leonhard Euler", "Mathematician", NA) 16 list(объект1, объект2, ...)
Greenland New Guinea Borneo Madagascar Baffin Sumatra Рис. 1.6. Круговая диаграмма > Euler [[1]] [1] "Leonhard Euler" [[2]] [1] "Mathematician" [[3]] [1] NA К компонентам можно обращаться по номеру. Номер указывается в двойных квадратных скобках после имени списка. Например, > Euler[[2]] [1] "Mathematician" > Euler[[3]] <- 1707 Можно создавать новые компоненты: > Euler[[4]] <- TRUE > Euler [[1]] 17 Euler[[2]] Euler[[4]] <- TRUE
Histogram of x x Frequency −2 −1 0 1 2 3 0 10 20 30 40 Рис. 1.7. Гистограмма [1] "Leonard Euler" [[2]] [1] "Mathematician" [[3]] [1] 1746 [[4]] [1] TRUE Функция list() без аргументов создает пустой список. Можно задать имена компонент так же, как мы задавали имена для ком- понент вектора: > names(Euler) <- c(’name’, ’occupation’, ’year’, ’married’) > Euler @name [1] "Leonhard Euler" @occupation 18 names(Euler)
[1] "Mathematician" @year [1] 1707 @married [1] TRUE Теперь к компонентам вектора можно обращаться по имени. Для этого есть две возможности. Имя можно указывать либо после знака @, который при- писывается к имени списка, например, Euler@occupation, либо в кавычках и двойных квадратных скобках, например, Euler[["occupation"]]. Последняя возможность удобна тем, что вместо самого имени компоненты может стоять имя переменной (разумеется, уже без кавычек) или даже целое выражение, значение которого есть имя компоненты. Имена компонент списка можно указать сразу при его создании: > Euler = list(name = "Leonhard Euler", occupation = "Mathematician") Одинарные квадратные скобки создают срезы списка. Например, lst[1:4] — список, состоящий из первых четырех компонент списка lst, lst[-(1:4)] — список, полученный исключением первых четырех компонент из списка lst , lst[c("name", "occupation")] — список, состоящий из указанных ком- понент вектора и т. д. Правила использования индексов аналогичны соответ- ствующим правилам для векторов. Важно понимать различие между правилами использования одинарных и двойных квадратных скобок. Например, lst[[1]] — это список, состоящий из первой компоненты списка lst, тогда как lst[1] — это сама первая компонен- та. Отметим также, что в двойных квадратных скобках в качестве индексов не могут использоваться векторы. Списки — это рекурсивный тип данных, т. е. компоненты списка могут сами быть списками. Например, > Pushkin <- list(name = "Александр Сергеевич Пушкин", year = 1799) > Gogol <- list(name = "Николай Васильевич Гоголь", year = 1809) > lst <- list(Pushkin, Gogol) > lst[[1]]@name [1] "Александр Сергеевич Пушкин" > length(lst) [1] 2 Функция c осуществляет конкатенацию двух или более списков. > clst <- c(Pushkin, Gogol) > clst @name [1] "Александр Сергеевич Пушкин" @year 19 Euler@occupation , Euler[["occupation"]] clst <- c(Pushkin, Gogol)
[1] 1799 @name [1] "Николай Васильевич Гоголь" @year [1] 1799 > length(clst) [1] 4 > clst@name [1] "Александр Сергеевич Пушкин" > clst@year [1] 1799 > clst[[3]] [1] "Николай Васильевич Гоголь" > clst[[4]] [1] 1809 1.11. Матрицы Числовую матрицу можно создать из числового вектора с помощью функ- ции matrix. Нужно указать число строк ncol = m и/или число столбцов ncol = m. В результате элементы из вектора будут записаны в матрицу указанных раз- меров. Например, > matrix(1:6, nrow = 2, ncol = 3) [,1] [,2] [,3] [1,] 1 3 5 [2,] 2 4 6 Длина вектора должна быть кратна произведению требуемого числа строк на требуемое число столбцов: > matrix(1, nrow = 2, ncol = 2) [,1] [,2] [1,] 1 1 [2,] 1 1 > matrix(1:2, nrow = 3, ncol = 2) [,1] [,2] [1,] 1 2 [2,] 2 1 [3,] 1 2 Если указывается только одна из размерностей (например, только число столб- цов), то она должна быть кратна длине вектора. Вторая размерность будет равна отношению длины вектора к первой размерности. 20 matrix ncol ncol
Как мы видим элементы записываются в матрицу по столбцам. Чтобы записать их по строкам, нужно задать значение дополнительного параметра byrow = TRUE : > matrix(1:6, nrow = 2, byrow=TRUE) [,1] [,2] [,3] [1,] 1 2 3 [2,] 4 5 6 Функции nrow(A) и ncol(B) возвращают число строк и столбцов матрицы A соответственно. Доступ к элементам матрицы происходит по индексу. A[i, j] ссылается на элемент i-й строки и j-го столбца матрицы A. На месте индексов i и j могут стоять векторы. Интерпретация такая же, как и у векторов. Если, например, i и j — это векторы с целыми положительными элементами, то A[i, j] есть подматрица матрицы A, образованная элементами, стоящими на пересечении строк с номерами из i и столбцов с номерами из j. Если, i и j — это векторы с целыми отрицательными элементами, то A[i, j] есть подматрица, полу- ченная из A вычеркиванием соответствующих строк и столбцов. Векторы i и j могут быть логическими или символьными. В последнем случае строкам и столбцам матрицы должны быть присвоены имена (см. ниже). A[i, ] эквивалетно A[i, 1:ncol(A)], а A[, j] эквивалетно A[1:nrow(A), j]. Возможен доступ к элементам матрицы с помощью одного индекса. На- пример, U[5] означает 5-й элемент матрицы U, если считать, что элементы перенумерованы по столбцам. Если i — вектор, то A[i] — означает выборку соответствующих элементов и т. д. Можно задать имена столбцам и строкам матрицы > A <- matrix(c(23, 31, 58, 16), nrow = 2) > rownames(A) <- c(’petal’, ’sepal’) > colnames(A) <- c(’length’, ’width’) После этого доступ к строкам и столбцам может происходить по имени. На- пример, A[’petal’, ’length]. Функция > A <- cbind(A, B) создает матрицу, приписывая к A справа B (для этого число строк у A и B должно совпадать). Функция > A <- rbind(A, B) создает матрицу, приписывая к A снизу B (для этого число столбцов у A и B должно совпадать). Заметим, что в списках аргументов функций cbind и rbind можно указать более двух матриц. Арифметические операции над матрицами осуществляются покомпонент- но, поэтому, например, чтобы сложить две матрицы, они должны иметь оди- наковые размеры: 21 byrow = TRUE : nrow(A) и ncol(B) A[i, ] эквивалетно A[i, 1:ncol(A)], а A[, j] эквивалетно A[1:nrow(A), j]. На месте индексов i и j могут стоять векторы. Интерпрет A[i, j] есть подматрица матрицы A A , образованная элементами, стоящими на пересечении строк с номерами из i и столбцов с номерами из j. Если i — вектор, то A[i] — означает выборку соответствующих элементов и rownames(A) <- colnames(A) cbind(A, B) rbind(A, B) Арифметические операции над матрицами осуществляются покомпонент- но, поэтому, например, чтобы сложить две матрицы, они должны иметь оди- наковые размеры: > A <- matrix(1:6, nrow = 2) > B <- matrix(-(1:6), nrow = 2) > A + B [,1] [,2] [,3] [1,] 0 0 0 [2,] 0 0 0 Впрочем, можно осуществлять смешанные операции, когда один из опе- рандов — матрица, а другой — вектор (в частности, скаляр). В этом случае матрица рассматривается как вектор, составленный из ее элементов, запи- санных по столбцам, и действуют те же правила, что и для арифметических операций над векторами: > (1:2)*A [,1] [,2] [,3] [1,] 1 3 5 [2,] 4 8 12 > (1:3) + A [,1] [,2] [,3] [1,] 2 6 7 [2,] 4 5 9 > A^2 [,1] [,2] [,3] [1,] 1 9 25 [2,] 4 16 36 Элементарные математические функции также применяются к элементам матрицы покомпонентно. Функция outer(x, y, op) применяет операцию op к каждой паре элемен- тов векторов x и y. На выходе получаем матрицу, составленную из результа- тов выполнения этой операции. Число строк матрицы есть длина вектора x, а число столбцов — длина вектора y. Например, > x <- 1:3 > x [1] 1 2 3 > y <- -2:2 > y [1] -2 -1 0 1 2 > outer(x, y, "+") [,1] [,2] [,3] [,4] [,5] [1,] -1 0 1 2 3 [2,] 0 1 2 3 4 [3,] 1 2 3 4 5 > outer(x, y, "*") [,1] [,2] [,3] [,4] [,5] [1,] -2 -1 0 1 2 [2,] -4 -2 0 2 4 [3,] -6 -3 0 3 6 22 Элементарные математические функции также применяются к элементам матрицы покомпонентно. outer(x, y, op)
Вместо outer(x, y, "*") (внешнее произведение векторов) можно использо- вать x %o% y. Транспонирование матрицы осуществляет функция t(A), а матричное про- изведение — операция %*%: > A <- matrix(1:6, nrow = 2) > B <- t(A) > A%*%B [,1] [,2] [1,] 35 44 [2,] 44 56 > B%*%A [,1] [,2] [,3] [1,] 5 11 17 [2,] 11 25 39 [3,] 17 39 61 Для решения системы линейных уравнений Ax = b с квадратной невырож- денной матрицей A есть функция solve(A, b): > A <- matrix(1:4, ncol = 2) > A [,1] [,2] [1,] 1 3 [2,] 2 4 > b = c(5, 8) > solve(A, b) [1] 2 1 det(A) находит определитель, а solve(A) — обратную матрицу: > det(A) > [1] -2 > solve(A) [,1] [,2] [1,] -2 1.5 [2,] 1 -0.5 Среди других процедур, относящихся к линейной алгебре, в R есть ме- тоды нахождения разложения Холецкого (функция chol), QR-разложения (chol), сингулярного разложения (svd), нахождение собственных векторов и собственных чисел (eigen) и др. 1.12. Многомерные массивы Матрицы — это частный случай многомерных массивов. Матрицы имеют две размерности. В общем случае массивы могут иметь больше размерностей. 23 t(A) t(A) , %*% : solve(A, b) : det(A) solve(A) (eigen)
Работа с многомерными массивами в R во многом аналогична. Основной спо- соб их создания — функция array. Указываются элементы массива и все его размерности. Например, создадим массив размера 2 × 3 × 4: > A = array(1:24, c(2, 3, 4)) > A , , 1 [,1] [,2] [,3] [1,] 1 3 5 [2,] 2 4 6 , , 2 [,1] [,2] [,3] [1,] 7 9 11 [2,] 8 10 12 , , 3 [,1] [,2] [,3] [1,] 13 15 17 [2,] 14 16 18 , , 4 [,1] [,2] [,3] [1,] 19 21 23 [2,] 20 22 24 Можно задать имена размерностям: > dim1 <- c(’Income’, ’Expence’) > dim2 <- c(’John’, ’George’, ’Paul’) > dim3 <- c(’Winter’,’Spring’,’Summer’,’Autumn’) > dimnames(A) <- list(dim1, dim2, dim3) и после этого обращаться к элементу по имени его строки, столбца, слоя и т. д. Заметим, что подобным образом происходит работа с массивами, состоя- щими из символьных строк, логическими массивами и массивами, получен- ными на основе списков. 1.13. Факторы Фактор — это векторный объект, кодирующий категориальные данные(классы). Факторы создаются с помощью функции factor. Предположим, что 24 array dim1 dimnames(A) factor у нас имеется 3 класса Yes, No, Perhaps. И некоторая выборка из 6 объектов, каждый из которых принадлежит одному из этих классов. Тогда > v = c("Yes", "No", "Yes", "Perhaps", "No", "Perhaps") > f = factor(v) > f [1] Yes No Yes Perhaps No Perhaps Levels: No Perhaps Yes > length(f) [1] 6 1.14. Фреймы данных Фреймы данных (data frames) — один из самых важных типов данных в R, позволяющий объединять данные разных типов вместе. Можно считать, что фрейм данных — эта двумерная таблица, в которой (в отличие от число- вых матриц), разные столбцы могут содержать данные разных типов (но все данные в одном столбце имеют один тип). Например, такая таблица может содержать результаты эксперимента. Создать фрейм данных можно с помощью функции data.frame: > frm <- data.frame(data1, data2, ...) Здесь многоточие означает, что список данных может содержать произволь- ное число элементов. В качестве данных (data1, data2, . . . ) могут выступать векторы (числовые, символьные или логические), факторы, матрицы (число- вые, символьные или логические), списки или другие фреймы. При этом все векторы должны иметь одинаковую длину, а матрицы и фреймы — одинако- вое (такое же) число строк. Могут также встречаться векторы, длина которых меньше, но в этом случае эта длина должна являться делителем максималь- ной встречающейся длины. То же требование предъявляется к компонентам списков. Функция data.frame просто собирает все данные вместе. Символь- ные векторы конвертируются в факторы. Остальные данные собираются во фрейм такими, какие они есть. Рассмотрим пример: > Y <- matrix(c(1950, 1980, 1973, 1995, 1978, 2001, 1983, 2005), nrow = 4) > rownames(Y) <- c("Иванов", "Петров", "Сидоров", "Смит") > colnames(Y) <- c("born", "entrance") > Y born entrance Иванов 1950 1978 Петров 1980 2001 Сидоров 1973 1983 Смит 1995 2005 > m <- c(TRUE, TRUE, TRUE, FALSE) 25 data.frame : В качестве данных ((data1 data1 , data2 data2 , . . . ) могут выступать векторы (числовые, символьные или логические), факторы, матрицы (число- вые, символьные или логические), списки или другие фреймы. При этом все векторы должны иметь одинаковую длину, а матрицы и фреймы — одинако- вое (такое же) число строк.
> c <- c(2, 1, 3, 0) > P <- data.frame(Y, m, c) > P born entrance m c Иванов 1950 1978 TRUE 2 Петров 1980 2001 TRUE 1 Сидоров 1973 1983 TRUE 3 Смит 1995 2005 FALSE 0 Мы видим, что в результате создан фрейм данных с 4 строками и 4 столбцами. Строкам и столбцам присвоены имена. В качестве имен строк и имен первых двух столбцов использованы имена строк и столбцов матрицы Y. Если бы строки и столбцы этой матрицы не были именованы, то имена для строк и столбцов результирующего фрейма назначаются автоматически. В качестве имен двух последних столбцов фрейма взяты имена переменных, из которых эти столбцы были получены. Имена можно изменить: > rownames(P) <- 1:4 > colnames(P)[3] <- "married" > colnames(P)[4] <- "nchildren" > P born entrance married nchildren 1 1950 1978 TRUE 2 2 1980 2001 TRUE 1 3 1973 1983 TRUE 3 4 1995 2005 FALSE 0 Если среди аргументов функции data.frame есть список, то каждая его компонента превращается в столбец фрейма. Например, > lst = list(1:4, TRUE, c("A", "B")) > data.frame(lst) X1.4 TRUE. c..A....B.. 1 1 TRUE A 2 2 TRUE B 3 3 TRUE A 4 4 TRUE B Доступ к элементам фрейма осуществляется двумя способами: в «матрич- ном» или «списковом» стилях. В первом случае указываются номера или име- на строки и столбца. Во втором фрейм рассматривается как список, компонен- тами которого являются столбцы фрейма, и чтобы обратиться к его элементу нужно указать имя или номер этой компоненты (т. е. имя или номер столбца), а затем имя или номер строки. Рассмотрим примеры: > P[1, "born"] [1] 1950 > P[4, 3] 26 Доступ к элементам фрейма осуществляется двумя способами: в «матрич- ном» или «списковом» стилях. rownames(P) colnames(P)[3] colnames(P)[4] <-
[1] FALSE > P[, "nchildren"] [1] 2 1 3 0 > P[2:3, ] X1 X2 married nchildren 2 1980 2001 TRUE 1 3 1973 1983 TRUE 3 > P$born [1] 1950 1980 1973 1995 > P$nchildren[3] [1] 3 > P[["born"]][2] [1] 1980 > P[[1]][2] [1] 1980 1.15. Графики функций двух переменных hot.colors <- function(n) { m <- trunc(n/3) m3 <- n - 2*m pas <- 0.75 r <- c(seq(0, pas, len = m), rep(1, n - m)) g <- c(rep(0, m), seq(0, pas, len = m), rep(1, n - 2*m)) b <- c(rep(0, 2*m), seq(0, pas, len = n - 2*m)) rgb(r, g, b) } n = 300 x <- y <- seq(-1, 1, len = n) X <- matrix(rep(x, n), nrow = n) Y <- t(X) Z <- (X^2 + Y^2)^3 - 4*X^2*Y^2 contour(x, y, Z, levels = c(-0.1, -0.05, -0.01, -0.001, 0, 0.1, 0.2), col = "blue") # filled.contour(x, y, Z, levels = c(-0.1, -0.05, -0.01, -0.001, 0, 0.1, 0.2), color.palette # persp(x, y, Z) # rainbow cm.colors topo.colors terrain.colors heat.colors n = 44 x <- y <- seq(-pi, pi, len = n) r <- (outer(x^2, y^2, "+")) z <- exp(-sqrt(r))*cos(r) 27
−1.0 −0.5 0.0 0.5 1.0 −1.0 −0.5 0.0 0.5 1.0 Рис. 1.8. Линии уровня функции y = (x 2 + y 2 ) 3 − 4x 2 y 2 persp(x, y, z, theta = 30, phi = 30, expand = 0.5, col = "red", ltheta = 120, shade = 0.4, ticktype 1.16. Ввод и вывод 1.17. Управляющие конструкции Каждая команда или выражение в языке R возвращает некоторый ре- зультат. Даже присваивание — это выражение, результат которого — при- сваиваемое значение. Выражение может быть частью другого выражения. В частности, возможны множественные присваивания, например, > x <- y <- z <- 0 Выражения можно объединять в блоки. Блок — это несколько выражений, заключенных в фигурные скобки. Сами выражения, как обычно, разделяют- ся точкой с запятой или символом перехода на новую строку. Результатом выполнения всего блока будет результат последнего из выражений, составля- ющих блок: > { 28 −0.10 −0.05 0.00 0.05 0.10 0.15 0.20 −1.0 −0.5 0.0 0.5 1.0 −1.0 −0.5 0.0 0.5 1.0 Рис. 1.9. Линии уровня с закрашенными промежутками x <- 7; y <- 8 x + y } [1] 15 Проверка условий осуществляется так же, как в языке C: > if (условие) выражение1 else выражение2 где условие — это логическое выражение, результат которого есть скаляр- ное логическое значение. Часто условия содержат логические операции &&, || . Тогда как &, | — покомпонентные операции, применяемые к векторам, && , || применяютя только к скалярным значениям и вычисляют свой второй операнд лишь при необходимости. Циклы с управляющей переменной реализуются с помощью конструкции > for (переменная in выражение1) выражение2 Результатом выражения1 должен быть вектор, при этом переменная на каж- дой итерации цикла принимает значение очередного элемента этого вектора. Количество итераций равно количеству элементов в векторе. > s = 0 29 if (условие) выражение1 else выражение2 & & , | — покомпонентные операции, применяемые к векторам, && && , || применяютя только к скалярным значениям и вычисляют свой второй операнд лишь при необходимости. for (переменная in выражение1) выражение2
x −2 0 2 y −2 0 2 z 0.0 0.2 0.4 0.6 0.8 Рис. 1.10. График функции z = cos(x 2 + y 2 )e √ (x 2 +y 2 ) > for (i in 1:20) s = s + i > s [1] 210 Заметим, что тот же результат быстрее можно получить с помощью команды sum(1:20) . Заметим, что циклы встречаются в R намного реже, чем в «тра- диционных» языках. Гораздо проще и эффективнее с точки зрения времени выполнения использовать функции, работающие сразу со всем объектом, чем с его частями. Циклы с предусловием реализуются с помощью конструкции > while (условие) выражение Преждевременный выход из цикла осуществляется командой break. Для пре- рывания текущей итерации и перехода к следующей служит команда next. Эти команды можно также использовать и с конструкцией for. «Бесконечный» цикл реализует команда > repeat выражение Внутри этой конструкции можно использовать команды break и next. 30 sum(1:20) break while (условие) выражение next > repeat выражение
1.18. Функции пользователя Формат определения функции следующий: > имя <- function(арг1, арг2, ...) выражение Здесь многоточие означает, что список формальных аргументов (формальных параметров ) арг1, арг2, . . . может иметь произвольную длину (в том числе, быть пустым). Как правило, выражение (тело функции) представляет собой блок. Значение, возвращаемое функцией, это значение этого выражения. До- срочное возвращение из функции осуществляет команда return(выражение1). В этом случае функция возвращает значение указанного выражения. Обращение к функции имеет вид имя(выражение1, выражение2, ...). Здесь значения выражений выражение1, выражение2, . . . являются фактическими арг- ментами, которые подставляются вместо соответствующих формальных аргу- ментов. Действуя обычным образом, меняя значения формальных аргументов внут- ри функции, вы не меняете соответствующих фактических аргументов. Един- ственный способ сделать это — использовать в теле функии «сильное» при- сваивание: arg1 <-- выражение Рассмотрим несколько простых примеров Если фактические аргументы заданы в «именованном» виде имя = выражение (многочисленные примеры этого мы видели раньше), то они могут быть пере- числены в произвольном порядке. Более того, список фактических аргумен- тов может начинаться с аргументов, представленных в обычной позиционной форме, после чего могут идти аргументы в именованной форме. Например, имеется функция fun, заданная следующим образом: > fun <- function(arg1, arg2, arg3, arg4) { # тело функции опущено } Тогда fun может быть вызвана многочисленными способами, например: > ans <- fun(d, f, 20, TRUE) > ans <- fun(d, f, arg4 = TRUE, arg3 = 20) > ans <- fun(arg1 = d, arg3 = 20, arg2 = f, arg4 = TRUE) Все эти способы эквивалентны. Во многих случаях при определении функции некоторым аргументам мо- гут быть присвоены значения по умолчанию. Тогда при вызове функции эти аргменты могут быть опущены. Предположим, что функция fun определена как > fun <- function(arg1, arg2, arg3 = 20, arg4 = TRUE) { # тело функции опущено } 31 имя <- function(арг1, арг2, ...) выражение выражение ((тело функции) представляет собой блок. Тогда обращение к этой функции вида > fun(d, f) Эквивалентно трем, приведенным выше. Следующее обращение > fun(d, f, arg4 = FALSE) меняет одно из значений по умолчанию. Заметим, что в значениях по умолчанию можно использовать любые вы- ражения, в том числе включающие другие аргменты функции. Все встречающиеся в теле функции символы делятся на три группы: это формальные аргументы, локальные переменные и свободные переменные. Формальные аргументы (формальные параметры) — это аргументы, пере- численные в заголовке функции (в круглых скобках после ключевого слова function Локальные переменные — это переменные, не являющиеся формальными аргументами, значения которых определяются во время выполнения функ- ции. Переменные, не являющиеся формальными аргументами и локальными переменными, являются свободными переменными. Например, в функции > f <- function(x) { y <- 2*x print(x) print(y) print(z) } x — формальный аргумент, y — локальная переменная, z — свободная пере- менная. Область видимости формальных аргументов и локальных переменных — только сама эта функция. Это означает, что изменения этих переменных внут- ри функции никак не отражаются на переменных с такими же именами во внешней функции. Область видимости свободных переменных распространя- ется до внешней функции, в которой они были определены. Изменение таких переменных в теле функции влияет также на соответствующие переменные в этой внешней функии. 1.19. boxplot и мозаичные диаграммы > colnames(chickwts) [1] "weight" "feed" > nrow(chickwts) [1] 71 >boxplot(weight feed, data = chickwts, col = "salmon", 32 >boxplot(weight feed, data = chickwts, col = "salmon",
casein linseed soybean 100 150 200 250 300 350 400 chickwt dataWeight at six weeks (gm) Рис. 1.11. boxplot varwidth = TRUE, notch = TRUE, main = "chickwt data", ylab = "Weight at six weeks (gm)") Графический результат см. на рис. 1.11. Таблица Titanic из библиотеки datasets содержит информацию о пасса- жирах Титаника. Таблица имеет 4 размерности: "Class" : Titanic["1st", , ,], Titanic["2nd", , ,], Titanic["3rd", , ,], Titanic["Crew", , ,] , "Sex" : Titanic[, "Male", ,], Titanic[, "Female", ,], "Age" : Titanic[, , "Child",], Titanic[, , "Adult",], "Survived" : Titanic[, , , "Yes"], Titanic[, , , "No"]. Элементы таблицы — количество человек из данной группы. Проверим нуль-гипотезу о том, что общее количество выживших пассажиров и членов экипажа не зависит от класса билета. Построим таблицу сопряженности при- знаков и мозаичную диаграмму: > titanic <- apply(Titanic, c(1, 4), sum) > titanic Survived Class No Yes 1st 122 203 33 varwidth = TRUE, notch = TRUE, main = "chickwt data", ylab = "Weight at six weeks (gm)") Titanic: class vs. survived Class Survived 1st 2nd 3rd Crew No Yes Рис. 1.12. Мозаичная диаграмма. Доля выживших на Титанике пассажиров и членов ко- манды в зависимости от класса их билета. 2nd 167 118 3rd 528 178 Crew 673 212 > mosaicplot(titanic, col = c("red", "green"), main = "Titanic: class vs survived") Графический результат см. на рис. 1.12. 1.19.1. Задания к лабораторной работе 1) Сгенерируйте вектор длины N=1000, элементами которого являются реа- лизации нормально распределенной случайной величины с математиче- ским ожиданием, равным 1, и стандартным отклонением, равным 0.3. Подсчитайте статистическое мат. ожидание и стандарную ошибку, не используя встроенные функции и проверьте правильность результата. Подсчитайте .95,.99-квантили. Исследуйте отклонение статистическо- го мат. ожидания от 1 при росте N (N=1000,2000,4000,8000). 2) Создайте фрейм данных из N=20 записей со следующими полями: Nrow — номер записи, Name — имя пользователя, BirthYear — год рождения, EmployYear — год приема на работу, Salary — зарплата, где Nrow изменя- 34 mosaicplot(titanic, col = c("red", "green"), main = "Titanic: class vs survived")
ется от 1 до N, Name задается произвольно, BithYear распределен равно- мерно на отрезке [1960,1985], EmployYear распределен равномерно на отрезке [BirthYear+18,2006], Salary для работников младше 1975 г.р. определяется по формуле Salary=(ln(2007-EmployYear)+1)*8000, для остальных Salary=(log2(2007-EmployYear)+1)*8000. Подсчитайте чис- ло сотрудников с зарплатой, большей 15000. Добавьте в таблицу поле, соответствующее суммарному подоходному налогу (ставка 13%), выпла- ченному сотрудником за время работы в организации, если его зарплата за каждый код начислялась согласно формулам для Salary, где вместо 2007 следует последовательно подставить каждый год работы сотрудни- ка в организации. 3) Напишите функцию, которая принимает на вход числовой вектор x и число разбиений интервала k (по умолчанию равное числу элементов вектора, разделенному на 10) и выполняет следующее: находит мини- мальное и максимальное значение элементов вектора xmin и xmax, раз- деляет полученный отрезок [xmin;xmax] на k равных интервалов и под- считывает число элементов вектора, принадлежащих каждому интер- валу. Далее должен строиться график, где по оси абсцисс — середины интервалов, по оси ординат — число элементов вектора, принадлежащих интервалу, разделенное на общее число точек. Проведите эксперимент на данной функции, где x — вектор длины 5000, сгенерированный из экспоненциально распределенной случайной величины,k=500. Прибли- жение какого графика мы получаем в итоге при большом числе точек и числе разбиений? 4) Спроектируйте и реализуйте метод наименьших квадратов. 35 |