Ссылки

  1. R project
  2. RStudio
  3. An Introduction to R
  4. Книги по R
  5. Quick-R

Начало работы с R

Установка

  1. Установить среду R
  2. Установить графическую оболочкуRStudio.
  3. Установка R Markdown (для создания автоматически генерируемых отчетов): в RStudio автоматически при первом создании файла с расширением “.Rmd”.
  4. Установка библиотек расширений: набрать в консоли install.packages(“pname”), где “pname” - название библиотеки. Полный список библиотек по ссылке Contributed extension packages, для просмотра по категориям нужно выбрать “CRAN Task Views”.

Для установка библиотек необходимо наличие выхода в Интернет.

Настройка RStudio для прокси-сервера
1. Установить прокси-сервер (для скачивания библиотек): ввести в консоли две команды

  1. Снять опцию “Use Internet Explorer library/proxy for HTTP” в Tools->Global Options->Packages

Создание отчетов с помощью R Markdown

  1. New File -> R Markdown …

Установливаются необходимые библиотеки… (при первом использовании)

  1. Набрать документ (правила набора: нажать на верхней части окна редактора на знак вопроса, выбрать “Markdown Quick Reference”)

  2. Далее нажать в выпадающем списке “Knit …” выбрать тип выходного документа (html, word, pdf)

Компиляция документа…

Загрузка установленной библиотеки

library(pname)

Сочетания клавиш

Очистить консоль - Ctrl+“L”

Ввод предыдущей команды - Стрелка ВВЕРХ

Выполнить выделенный код (для выполнения строки кода в файлах с расширениями .R и .Rmd) - Ctrl+Enter

Рабочая директория

#текущая рабочая директория
getwd()
## [1] "C:/temp/RWorkspace/course"
#установка рабочей директории
setwd("C:/temp/RWorkspace")

Опции рабочей сессии

#установка числа десятичных разрядов при выводе на консоль
options(digits=4)

Справка

#Поиск по точному названию функции
?options
## starting httpd help server ... done
#Поиск функции по частичному совпадению
apropos("solve")
## [1] "backsolve"     "forwardsolve"  "qr.solve"      "solve"        
## [5] "solve.default" "solve.qr"

Консоль

#Вывод в текстовый файл
sink("log.txt")
print("Hello from R!")
## [1] "Hello from R!"
#Возвращение вывода на консоль
sink()

#Сохранение истории комманд
#savehistory(file="commands.R")
#Выполнение всех сохраненных комманд
#для того, чтобы видеть комманды - ввести опцию echo=T
#source("commands.R") 

Рабочее пространство

Управление переменными

x=1;y=c(1,2,3)
#Просмотр списка текущих объектов (переменных)
ls()
## [1] "linmod" "qc"     "res"    "x"      "y"
#C отображением скрытых переменных
ls(all.names=TRUE)
## [1] ".CourseraLogin" ".Random.seed"   "linmod"         "qc"            
## [5] "res"            "x"              "y"
#Удаление переменной
rm(x)
#Удаление всех переменных
rm(list=ls())

Сохранение и восстановление рабочего пространства

x=1;y=c(1,2,3); z="Hello from R"

#Сохранить заданные переменные
save(x, y,z, file = "xyz.RData")
#Сохранить все переменные
save(list=ls(), file = "all.RData")
#Сохранить все рабочее пространство
save.image() # ~ save(list = ls(all = TRUE), file = ".RData")

#Загрузить переменные из файла
load(file = "xyz.RData")

Имена переменных

  1. Буквы,цифры, “_“,”."
  2. Первый символ - буква или “.” (x,x.a,x1_2)
  3. Первый символ “.”: скрытые (служебные переменные) (.Random.seed), после первой точки - обязательно буква

Арифметические операции

Присваивание

#Новый стиль
x=10
#Для совместимости с первыми версиями R и языком S
x<-10
#Аналогично предыдущему
10->x
# Аналогично с помощью функции
assign("x",10)
#Операция присваивания - тоже функция
`=`(x,10)

Скалярные операции

Арифметические операции и математические функции

 angle=60
 sin(angle*pi/180)+floor(2*3+3^11-sqrt(10)) #pi - константа
## [1] 177150
 #целая часть от деления
 10 %/% 3
## [1] 3
 #остаток от деления
 10 %% 3
## [1] 1

Арифметические операции - тоже функции

`+`(2,2)
## [1] 4

Операции с комплексными числами

sqrt(-17)
## Warning: созданы NaN
## [1] NaN
sqrt(-17+0i)
## [1] 0+4.123i

Основной элемент - вектор

Создание вектора

#c помощью оператора ":"
(x=1:10)
##  [1]  1  2  3  4  5  6  7  8  9 10
#с помощью функции c()
#числовой вектор
angle=c(30,60,90); print(angle)
## [1] 30 60 90
#получить длину вектора
length(angle)
## [1] 3
#вектор из строк
(angle.names=c("thirty","sixty","ninety"))
## [1] "thirty" "sixty"  "ninety"
rad=angle*pi/180
rad=c(rad,pi,rad)
print(rad)
## [1] 0.5236 1.0472 1.5708 3.1416 0.5236 1.0472 1.5708
#Использования имени функции для пользовательской переменной
с=1;c
## function (..., recursive = FALSE)  .Primitive("c")
#но
(c(1,2,3))
## [1] 1 2 3
#вектор нулевой длины
x=numeric(0)
print(x)
## numeric(0)

Базовые векторные операции

rad=angle*pi/180
print(rad)
## [1] 0.5236 1.0472 1.5708
(x=rad^2+1)
## [1] 1.274 2.097 3.467
x=1:10;y=c(1,1000)
#Значение вектора y циклически повторяются
(x+y)
##  [1]    2 1002    4 1004    6 1006    8 1008   10 1010

Типы данных в R

Числовые данные

#целочисленные: индексы
x=1:7

str(x)
##  int [1:7] 1 2 3 4 5 6 7
is.integer(x)
## [1] TRUE
is.numeric(x)
## [1] TRUE
is.finite(x)
## [1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE
#вещественные: введенные с помощью функции с 
#данные о зарплате сотрудников
salary <- c(500, 600, 400, 650, 300,550,2000)

str(salary)
##  num [1:7] 500 600 400 650 300 550 2000
is.numeric(salary)
## [1] TRUE
is.vector(salary)
## [1] TRUE
#рост сотрудников, м
height=c(1.75,1.80,1.90,1.65,1.70,1.72,1.85)
is.numeric(height)
## [1] TRUE

Текстовые данные

#имена сотрудников
name=c("Иван", "Алексей", "Александр", "Анна","Татьяна", "Валентин", "Андрей")

str(name)
##  chr [1:7] "Иван" "Алексей" "Александр" "Анна" "Татьяна" ...
is.character(name)
## [1] TRUE
is.character(salary)
## [1] FALSE
is.character(as.character(salary))
## [1] TRUE
#пол сотрудников
sex <- c("male", "male", "male", "female", "female", "male", "male")
table(sex)
## sex
## female   male 
##      2      5

Логические

#является ли зарплата больше средней?
check=(salary >500)
 
str(check)
##  logi [1:7] FALSE TRUE FALSE TRUE FALSE TRUE ...
is.logical(check)
## [1] TRUE

Пропущенные данные

#NA : Not Available - значения нет
(z=c(1:3,NA))
## [1]  1  2  3 NA
is.na(z)
## [1] FALSE FALSE FALSE  TRUE
  #Пример- девушки не захотели назвать свой вес
(weight=c(82, 87, 93, NA, NA, 72, 82))
## [1] 82 87 93 NA NA 72 82
#NaN : Not a Number - значение неопределено
print(0/0)
## [1] NaN
(x=c(z,Inf-Inf))
## [1]   1   2   3  NA NaN
#тестирование на пропущенные значения
is.na(x)
## [1] FALSE FALSE FALSE  TRUE  TRUE
is.nan(x)
## [1] FALSE FALSE FALSE FALSE  TRUE

Шкалы измерений

#количественная: размер зарплаты
str(salary)
##  num [1:7] 500 600 400 650 300 550 2000
#порядковая шкала: размер одежды
size=c("XLL", "S", "XL", "S", "S", "M", "L")
str(size)
##  chr [1:7] "XLL" "S" "XL" "S" "S" "M" "L"
#номинальная шкала: имя
str(name)
##  chr [1:7] "Иван" "Алексей" "Александр" "Анна" "Татьяна" ...

Структуры данных: доступ и атрибуты

Векторы

Индексирование

salary #весь вектор
## [1]  500  600  400  650  300  550 2000
salary[7]
## [1] 2000
#индекс может быть и к нескольким элементам сразу
salary[c(1,3,5,7)]
## [1]  500  400  300 2000
salary[1:3]
## [1] 500 600 400
#можно выбрать все кроме 7-го элемента:
salary[-7]
## [1] 500 600 400 650 300 550
#или кроме первых трех элементов
salary[-(1:3)]
## [1]  650  300  550 2000
#c помощью условного вектора
idx=salary>500; salary[idx]
## [1]  600  650  550 2000
#или короче
salary[salary>500]
## [1]  600  650  550 2000

Индексирование с присваиванием

#есть пропущенные значения
weight
## [1] 82 87 93 NA NA 72 82
#присвоим всем пропущенным средний вес человека на Земле
weight[is.na(weight)]=62
print(weight)
## [1] 82 87 93 62 62 72 82
#можно было присвоить сразу нескольким элементам
(weight=c(82, 87, 93, NA, NA, 72, 82))
## [1] 82 87 93 NA NA 72 82
weight[is.na(weight)]=c(60,62)
print(weight)
## [1] 82 87 93 60 62 72 82

Атрибуты

#внутренние (intrinsic) атрибуты
mode(salary) #тип данных
## [1] "numeric"
length(salary) #длина вектора
## [1] 7
#увеличим длину вектора
length(salary)=10
#теперь имеем пропущенные значения
salary
##  [1]  500  600  400  650  300  550 2000   NA   NA   NA
length(salary)=7 #прежнее значение 
#атрибут "метки"
str(salary) #индексы по умолчанию - порядковые номера
##  num [1:7] 500 600 400 650 300 550 2000
names(salary)=c("Иван", "Алексей", "Александр", "Анна",
                "Татьяна", "Валентин", "Андрей")
#теперь имеем именованный вектор
str(salary)
##  Named num [1:7] 500 600 400 650 300 550 2000
##  - attr(*, "names")= chr [1:7] "Иван" "Алексей" "Александр" "Анна" ...
salary
##      Иван   Алексей Александр      Анна   Татьяна  Валентин    Андрей 
##       500       600       400       650       300       550      2000
#и можно обращаться с помощью текстовых индексов
salary[c("Татьяна","Андрей")]
## Татьяна  Андрей 
##     300    2000
#получить атрибут "names" у переменной "salary"
attr(salary,"names")
## [1] "Иван"      "Алексей"   "Александр" "Анна"      "Татьяна"   "Валентин" 
## [7] "Андрей"
#удалить данный атрибут
attr(salary,"names")=NULL
print(salary)
## [1]  500  600  400  650  300  550 2000
#можно придумать свои атрибуты
attr(salary,"Less 500")=salary<500
str(salary)
##  atomic [1:7] 500 600 400 650 300 550 2000
##  - attr(*, "Less 500")= logi [1:7] FALSE FALSE TRUE FALSE TRUE FALSE ...
attr(salary,"Less 500")<-NULL

Матрицы

Матрица - обобщение вектора

m1=matrix(c(1,2,3,4),nrow=2,ncol=2) #достаточно только указать nrow=2 или ncol=2
#по умолчанию заполняются столбцы матрицы
m1
##      [,1] [,2]
## [1,]    1    3
## [2,]    2    4
#опция byrow=T позволяет заполнять матрицу построчно
m1=matrix(c(1,2,3,4),nrow=2,byrow=T);m1
##      [,1] [,2]
## [1,]    1    2
## [2,]    3    4
#значения исходного вектора циклически повторяются
x=1:3;matrix(x,nrow=2,ncol=3)
##      [,1] [,2] [,3]
## [1,]    1    3    2
## [2,]    2    1    3
#нулевая матрица
matrix(0,nrow=2,ncol=3)
##      [,1] [,2] [,3]
## [1,]    0    0    0
## [2,]    0    0    0
#проверка на тип данных
is.numeric(m1)
## [1] TRUE
#проверка, что объект является матрицей
is.matrix(m1)
## [1] TRUE
#представление в текстовой форме
str(m1)
##  num [1:2, 1:2] 1 3 2 4
#атрибуты
dim(m1) #размерность матрицы
## [1] 2 2
ncol(m1) #количество столбцов
## [1] 2
#получение матрицы с помощью атрибута dim
m2=1:20
dim(m2)=c(4,5) #элементы вектора заносятся по столбцам
m2
##      [,1] [,2] [,3] [,4] [,5]
## [1,]    1    5    9   13   17
## [2,]    2    6   10   14   18
## [3,]    3    7   11   15   19
## [4,]    4    8   12   16   20
#именование индексов матрицы
colnames(m2) #по умолчанию - нет названий столбцов
## NULL
colnames(m2)=c("a","b","c","d","e")
m2 #теперь столбцы именованные
##      a b  c  d  e
## [1,] 1 5  9 13 17
## [2,] 2 6 10 14 18
## [3,] 3 7 11 15 19
## [4,] 4 8 12 16 20
rownames(m2)=c("alpha","beta","gamma","delta")
m2
##       a b  c  d  e
## alpha 1 5  9 13 17
## beta  2 6 10 14 18
## gamma 3 7 11 15 19
## delta 4 8 12 16 20

общий случай - многомерный массив (array)

m3=1:24
dim(m3)=c(3,4,2) # m3=array(m3,dim=c(3,4,2))
m3
## , , 1
## 
##      [,1] [,2] [,3] [,4]
## [1,]    1    4    7   10
## [2,]    2    5    8   11
## [3,]    3    6    9   12
## 
## , , 2
## 
##      [,1] [,2] [,3] [,4]
## [1,]   13   16   19   22
## [2,]   14   17   20   23
## [3,]   15   18   21   24

Индексирование

#индексы-числа
m2[2,3]
## [1] 10
m2[c(1,2),c(3,4)]
##        c  d
## alpha  9 13
## beta  10 14
m2[2,] #извлечь вторую строку
##  a  b  c  d  e 
##  2  6 10 14 18
m2[,1:3] #извлечь первые три столбца
##       a b  c
## alpha 1 5  9
## beta  2 6 10
## gamma 3 7 11
## delta 4 8 12
m2[-1,] #извлечь все строки, кроме первой
##       a b  c  d  e
## beta  2 6 10 14 18
## gamma 3 7 11 15 19
## delta 4 8 12 16 20
#индексы-метки
m2["beta",]
##  a  b  c  d  e 
##  2  6 10 14 18
m2[,c("a","b")]
##       a b
## alpha 1 5
## beta  2 6
## gamma 3 7
## delta 4 8
#индекс-матрица
(i <- array(c(1:3,3:1), dim=c(3,2)))
##      [,1] [,2]
## [1,]    1    3
## [2,]    2    2
## [3,]    3    1
m2[i]
## [1] 9 6 3
#присвоить элементам матрицы значение 0
m2[i]=0;m2
##       a b  c  d  e
## alpha 1 5  0 13 17
## beta  2 0 10 14 18
## gamma 0 7 11 15 19
## delta 4 8 12 16 20

Факторы

Получение фактора из категоральной переменной “sex”

#sex <- c("male", "male", "male", "female", "female", "male", "male")
sex.f=factor(sex) #аналогично sex.f=as.factor(sex)
is.factor(sex.f)
## [1] TRUE
str(sex.f) #текстовое представление фактора - метки (labels)
##  Factor w/ 2 levels "female","male": 2 2 2 1 1 2 2
labels(sex.f)
## [1] "1" "2" "3" "4" "5" "6" "7"
print(sex.f) #внешнее представление - уровни (levels)
## [1] male   male   male   female female male   male  
## Levels: female male
levels(sex.f) #глаыный атрибут фактора
## [1] "female" "male"
table(sex.f) # получить частоты
## sex.f
## female   male 
##      2      5
plot(sex.f) #график частот

plot of chunk unnamed-chunk-24

print(as.numeric(sex.f)) # факторы легко преобразуются в количественные переменные
## [1] 2 2 2 1 1 2 2

Получение фактора из количественной переменной

#преобразование количественной шкалы к порядковой - фактору
salary.ranges=cut(x=salary,breaks=c(0,500,2000))
str(salary.ranges)
##  Factor w/ 2 levels "(0,500]","(500,2e+03]": 1 2 1 2 1 2 2
table(salary.ranges)
## salary.ranges
##     (0,500] (500,2e+03] 
##           3           4
#изменим атрибут "salary"
levels(salary.ranges)=c("Low","High")
print(salary.ranges)
## [1] Low  High Low  High Low  High High
## Levels: Low High

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

size=c("XXL", "S", "XL", "S", "S", "M", "L")
(size.f=factor(size)) #неупорядоченный
## [1] XXL S   XL  S   S   M   L  
## Levels: L M S XL XXL
(ordered(size.f, levels=c("S", "M", "L", "XL", "XXL")))
## [1] XXL S   XL  S   S   M   L  
## Levels: S < M < L < XL < XXL

Списки

Списки содержат разнородные элементы

#лист объединяет данные всех типов
family = list(husband="Fred", wife="Mary", nchildren=3,
         child.ages=c(4,7,9));family
## $husband
## [1] "Fred"
## 
## $wife
## [1] "Mary"
## 
## $nchildren
## [1] 3
## 
## $child.ages
## [1] 4 7 9
str(family)
## List of 4
##  $ husband   : chr "Fred"
##  $ wife      : chr "Mary"
##  $ nchildren : num 3
##  $ child.ages: num [1:3] 4 7 9
#индексы
family["wife"] # оператор "[]" выдает то же тип данных - лист размерности 1
## $wife
## [1] "Mary"
family[2] #можно пользоваться и индексом
## $wife
## [1] "Mary"
family[["wife"]] # оператор "[[]]" выдает атомарный тип - строку
## [1] "Mary"
family$wife # $ аналогично [[]]
## [1] "Mary"
#добавим новый элемент
family$granny="Anna"
names(family) #теперь есть новый элемент "granny"
## [1] "husband"    "wife"       "nchildren"  "child.ages" "granny"

Таблицы данных

Объединяют свойства матриц и списков

#создадим таблицу данных о сотрудниках
staff <- data.frame(v1=name,v2=salary,v3=sex.f,v4=weight, v5=height,v6=size,
                    stringsAsFactors = FALSE)
staff
##          v1   v2     v3 v4   v5  v6
## 1      Иван  500   male 82 1.75 XXL
## 2   Алексей  600   male 87 1.80   S
## 3 Александр  400   male 93 1.90  XL
## 4      Анна  650 female 60 1.65   S
## 5   Татьяна  300 female 62 1.70   S
## 6  Валентин  550   male 72 1.72   M
## 7    Андрей 2000   male 82 1.85   L
#зададим имена переменных
names(staff)=c("name","salary","sex","weight","height","size")
staff
##        name salary    sex weight height size
## 1      Иван    500   male     82   1.75  XXL
## 2   Алексей    600   male     87   1.80    S
## 3 Александр    400   male     93   1.90   XL
## 4      Анна    650 female     60   1.65    S
## 5   Татьяна    300 female     62   1.70    S
## 6  Валентин    550   male     72   1.72    M
## 7    Андрей   2000   male     82   1.85    L
#скроем вес женщин 
staff$weight[staff$sex=="female"]=NA
#текстовое представление
str(staff)
## 'data.frame':    7 obs. of  6 variables:
##  $ name  : chr  "Иван" "Алексей" "Александр" "Анна" ...
##  $ salary: num  500 600 400 650 300 550 2000
##  $ sex   : Factor w/ 2 levels "female","male": 2 2 2 1 1 2 2
##  $ weight: num  82 87 93 NA NA 72 82
##  $ height: num  1.75 1.8 1.9 1.65 1.7 1.72 1.85
##  $ size  : chr  "XXL" "S" "XL" "S" ...
#присвоим каждой строке метку
row.names(staff)=letters[1:nrow(staff)];staff
##        name salary    sex weight height size
## a      Иван    500   male     82   1.75  XXL
## b   Алексей    600   male     87   1.80    S
## c Александр    400   male     93   1.90   XL
## d      Анна    650 female     NA   1.65    S
## e   Татьяна    300 female     NA   1.70    S
## f  Валентин    550   male     72   1.72    M
## g    Андрей   2000   male     82   1.85    L
#извлечем данные об одном сотруднике
staff[staff$name=="Иван",]
##   name salary  sex weight height size
## a Иван    500 male     82   1.75  XXL
#Извлечем данные по зарплатам
staff$salary
## [1]  500  600  400  650  300  550 2000
#извлечем данные о зарплате среди женщин
staff[staff$sex=="female","salary"]
## [1] 650 300
#извлечем имена работников
#оператор "[]" извлекает таблицу данных
staff["name"]
##        name
## a      Иван
## b   Алексей
## c Александр
## d      Анна
## e   Татьяна
## f  Валентин
## g    Андрей
#оператор "[[]]" извлекает вектор
staff[["name"]]
## [1] "Иван"      "Алексей"   "Александр" "Анна"      "Татьяна"   "Валентин" 
## [7] "Андрей"
#извлечем первые три строки
staff[1:3,]
##        name salary  sex weight height size
## a      Иван    500 male     82   1.75  XXL
## b   Алексей    600 male     87   1.80    S
## c Александр    400 male     93   1.90   XL
#то же самое с помощью меток
staff[c("a","b","c"),]
##        name salary  sex weight height size
## a      Иван    500 male     82   1.75  XXL
## b   Алексей    600 male     87   1.80    S
## c Александр    400 male     93   1.90   XL
#отсортируем таблицу данных по имени и зарплате
staff[order(staff$name, staff$salary), ]
##        name salary    sex weight height size
## c Александр    400   male     93   1.90   XL
## b   Алексей    600   male     87   1.80    S
## g    Андрей   2000   male     82   1.85    L
## d      Анна    650 female     NA   1.65    S
## f  Валентин    550   male     72   1.72    M
## a      Иван    500   male     82   1.75  XXL
## e   Татьяна    300 female     NA   1.70    S

Чтение данных из файла

#запишем данные о сотрудниках в файл "staff.txt" (разделитель - табуляция)
write.table(staff,"staff.txt",sep="\t",fileEncoding="UTF-8")
#удалим таблицу данных из оперативной памяти
rm(staff)
staff #данных не найдено
## Error: объект 'staff' не найден
#прочитаем заново данные
#header=TRUE: читать имена переменных (заголовки) из первой строки
#encoding="UTF-8": для чтения кириллицы (имена сотрудников)
staff=read.table("staff.txt",header=TRUE,sep="\t",encoding="UTF-8")

Присоединение таблицы данных к текущему окружению

#просмотрим список текущих переменных
ls()
## [1] "staff"
salary # переменной "salary" нет
## Error: объект 'salary' не найден
#присоединяем таблицу данных
attach(staff)
#теперь можем обращаться к переменным из таблицы данных
salary
## [1]  500  600  400  650  300  550 2000
#отсоединяем: надо всегда делать при окончании работы
#с данной таблицей данных
detach(staff)

Векторизированнные вычисления

Генерация последовательностей

Операция “:”

(s=1:10)
##  [1]  1  2  3  4  5  6  7  8  9 10
print(pi:10)
## [1] 3.142 4.142 5.142 6.142 7.142 8.142 9.142

Функция seq

#Первый способ
(s1=seq(-3,3,0.5))
##  [1] -3.0 -2.5 -2.0 -1.5 -1.0 -0.5  0.0  0.5  1.0  1.5  2.0  2.5  3.0
#Второй способ
(s2=seq(from=-3,to=3,by=0.5))
##  [1] -3.0 -2.5 -2.0 -1.5 -1.0 -0.5  0.0  0.5  1.0  1.5  2.0  2.5  3.0
#Третий способ
(s3=seq(length=13,from=-3,by=0.5))
##  [1] -3.0 -2.5 -2.0 -1.5 -1.0 -0.5  0.0  0.5  1.0  1.5  2.0  2.5  3.0

Функция rep

s=c(1,2,3)
rep(s,times=3)
## [1] 1 2 3 1 2 3 1 2 3
rep(s,each=3)
## [1] 1 1 1 2 2 2 3 3 3

Матричные операции

Над векторами

x=1:2;y=3:4
#скалярное произведение (inner product)
x %*% y
##      [,1]
## [1,]   11
#внешнее произведение (outer product)
x %o% y #аналогично x %*% t(y)
##      [,1] [,2]
## [1,]    3    4
## [2,]    6    8

Над матрицами

m1=m2=matrix(c(1,2,3,4),nrow=2);m1
##      [,1] [,2]
## [1,]    1    3
## [2,]    2    4
#функции rbind,cbind - получение составной матрицы
rbind(m1,m2) # по строкам
##      [,1] [,2]
## [1,]    1    3
## [2,]    2    4
## [3,]    1    3
## [4,]    2    4
cbind(m1,m2) # по столбцам
##      [,1] [,2] [,3] [,4]
## [1,]    1    3    1    3
## [2,]    2    4    2    4
# функция t: транспонировать матрицу
t(m1)
##      [,1] [,2]
## [1,]    1    2
## [2,]    3    4
#скалярное умножение матриц (аналогично для операции деления "/")
m1*m2
##      [,1] [,2]
## [1,]    1    9
## [2,]    4   16
#вычислить матричное выражение
m1+m2-12*m2+1
##      [,1] [,2]
## [1,]   -9  -29
## [2,]  -19  -39
#матричное умножение 
m1 %*% m2
##      [,1] [,2]
## [1,]    7   15
## [2,]   10   22
#умножить на вектор
m1 %*% 1:2
##      [,1]
## [1,]    7
## [2,]   10
# crossprod(m1,m2)=t(m1)*m2
crossprod(m1,m2)
##      [,1] [,2]
## [1,]    5   11
## [2,]   11   25
#диагональ маттрицы
diag(m1)
## [1] 1 4
#определитель матрицы
det(m1)
## [1] -2

Численные методы

#обратить матрицу
solve(matrix(c(1,2,2,5),nrow=2))
##      [,1] [,2]
## [1,]    5   -2
## [2,]   -2    1
#решить систему линейных уравнений с матрицей A и свободным вектором b
A=matrix(1:4,nrow=2);b=c(5,6)
solve(A,b) # лучше, чем solve(A) %*% b
## [1] -1  2
#найти собственные значения и вектора
ev=eigen(A)
ev$values #собственные значения
## [1]  5.3723 -0.3723
ev$vectors #Собственные вектора
##         [,1]    [,2]
## [1,] -0.5658 -0.9094
## [2,] -0.8246  0.4160
#разложение холецкого A=t(B) %*% B, A - положительно определенная
A=matrix(c(1,2,2,5),nrow=2)
(B=chol(A))
##      [,1] [,2]
## [1,]    1    2
## [2,]    0    1
t(B) %*% B
##      [,1] [,2]
## [1,]    1    2
## [2,]    2    5

Циклические функции

apply, tapply, sapply, lapply

apply

#извлечем из данных только количественные переменные
(staff.num=staff[c("salary","weight","height")])
##   salary weight height
## a    500     82   1.75
## b    600     87   1.80
## c    400     93   1.90
## d    650     NA   1.65
## e    300     NA   1.70
## f    550     72   1.72
## g   2000     82   1.85
#применим функцию "mean" (среднее) к каждому столбцу
#параметр "2" означает по второму измерению (столбцу)
apply(staff.num,2,mean)
##  salary  weight  height 
## 714.286      NA   1.767
#можно применить любую другую функцию, даже анонимную
#здесь аргумент "х" принимает поочередно принимает значения
#каждого перебираемого столбца
#sd - станд. отклонение
apply(staff.num, 2, function(x) {mean(x)/sd(x)})
## salary weight height 
##  1.233     NA 20.107
#пример вычисления apply по строкам
(m=matrix(1:6,nrow=3))
##      [,1] [,2]
## [1,]    1    4
## [2,]    2    5
## [3,]    3    6
apply(m,1,sum) #подсчет суммы элементов в строке матрицы
## [1] 5 7 9

tapply

#подсчитаем макс. зарплату среди мужчин и женщин
#tapply позволяет разделить значения по переменной sex на два множества
#и применить функцию (в данном случае - max) к каждому множ. отдельно
tapply(staff$salary,staff$sex,max)
## female   male 
##    650   2000

sapply

#преобразуем все переменные таблицы данных в количественные
#sapply сохраняет структуру данных
sapply(staff, as.numeric)
##      name salary sex weight height size
## [1,]    6    500   2     82   1.75    5
## [2,]    2    600   2     87   1.80    3
## [3,]    1    400   2     93   1.90    4
## [4,]    4    650   1     NA   1.65    3
## [5,]    7    300   1     NA   1.70    3
## [6,]    5    550   2     72   1.72    2
## [7,]    3   2000   2     82   1.85    1

lapply

#проверим, какие переменные в таблице - факторы
#результат lapply - всегда список (в отличие от sapply)
sapply(staff, is.factor)
##   name salary    sex weight height   size 
##   TRUE  FALSE   TRUE  FALSE  FALSE   TRUE

Управляющие конструкции и функции

Условия

x=300
#результат логического выражения - скаляр
if (x>500) "Normal" else "Low"
## [1] "Low"
#если надо записать несколько команд - запись  условия следующая
if(x>500){
  temp="Normal"
  print(temp)
} else{
  temp="Low"
  print(temp)
}
## [1] "Low"
#результат логического выражения - вектор
ifelse(staff$salary>500,"Normal","Low")
## [1] "Low"    "Normal" "Low"    "Normal" "Low"    "Normal" "Normal"

Циклы

Индексирование в цикле for

#индекс поочередно выбирается из последовательности
#последовательность - вектор из элементов 1,2,...,100
s=0
for (i in 1:100){
  s=s+i
}
s
## [1] 5050
#последовательность - буквы
s=""
for (c in letters){
  s=paste(s,c)
}
s
## [1] " a b c d e f g h i j k l m n o p q r s t u v w x y z"
#последовательность переменные таблицы
#результат похож на lapply(staff,class)
for (var in staff){
  print(class(var))
}
## [1] "factor"
## [1] "integer"
## [1] "factor"
## [1] "integer"
## [1] "numeric"
## [1] "factor"

Сравнение эффективности векторных функций и циклов

# C помощью цикла
t0=proc.time()
s=0
for (i in 1:10^6) s=s+i
t1=proc.time()
t1-t0
##    user  system elapsed 
##    0.38    0.00    0.38
#c помощью встроенной функции
t0=proc.time()
sum(as.numeric(1:10^6))
## [1] 5e+11
t1=proc.time()
t1-t0
##    user  system elapsed 
##    0.06    0.00    0.06

Структура функции

Общий вид функции

arg1 - обязательный параметр: должен быть задан при вызове функции
arg2,arg3 - необязательные параметры, если не заданы, то используются значения по умолчанию
… - список параметров, которые могут быть далее переданы функции f0

f=function(arg1,arg2=0,arg3=“a”,…){

if(arg3==“a”){
temp=arg1+arg2
} else{
temp=f0(arg1,…)
}

return(temp)# или просто temp
}

Пример функции

#пример функции - staff.subset
#функция извлекает подбыборку из таблицы данных staff (обязат. аргумент)
#sex: извлекаются данные о сотрудниках определенного пола (или одновр. М и Ж)
#order: если указана переменная var, то данные перед выводом сортируются по ней
#если переменная указана, то по ней вычисляется среднее
staff.subset = function(staff, sex="all", var=FALSE,...){
  #проверить,что staff действительно - таблица данных
  if(!is.data.frame(staff)) stop("Invalid data")
  
  #выбрать данные, согласно sex
  if(sex=="all"){
    temp=staff
  }else{
    #проверка, что значение параметра sex действительно есть в выборке
    if (!(sex %in% staff$sex)) stop("Invalid sex")
    temp=staff[staff$sex==sex,]
  }
  
  #отсоритровать по переменной var (или не сортировать)
  if(var!=FALSE){
    #проверить, что данная переменная есть в данных
    if(!var %in% names(staff)) stop("Invalid variable")
    #найти среднее по переменной  var
    #если были переданы дополнительные параметры в staff.subset (вместо ...),
    #то они передаются в mean (также на место ...)
    #распечатать среднее по данной переменной
    mu=mean(temp[,var],...)
    cat("mean of ", var , " = ", mu, "\n")
    
    #отсортировать данные и вывести
    #результата этой строки будет выведен как последнее вычисляемое выражение
    #можно вписать эту строку в return() - результат аналогичный
    temp[order(temp[[var]]),]
  }else{
    #также выводится как результат функции
    temp #можно записать return(temp)
  }
  
}

Загрузка кода функции из файла

source(“staff_subset.R”)

Порядок вызова аргументов

Используем только, что созданную функцию

#просмотрим вначале исходную таблицу данных
staff
##        name salary    sex weight height size
## a      Иван    500   male     82   1.75  XXL
## b   Алексей    600   male     87   1.80    S
## c Александр    400   male     93   1.90   XL
## d      Анна    650 female     NA   1.65    S
## e   Татьяна    300 female     NA   1.70    S
## f  Валентин    550   male     72   1.72    M
## g    Андрей   2000   male     82   1.85    L
#передадим эту таблицу в функцию, остальные параметры - по умолчанию
staff.subset(staff)
##        name salary    sex weight height size
## a      Иван    500   male     82   1.75  XXL
## b   Алексей    600   male     87   1.80    S
## c Александр    400   male     93   1.90   XL
## d      Анна    650 female     NA   1.65    S
## e   Татьяна    300 female     NA   1.70    S
## f  Валентин    550   male     72   1.72    M
## g    Андрей   2000   male     82   1.85    L
#попробуем передать вектор вместо таблицы
staff.subset(1:10)
## Error: Invalid data
#выведем данные по мужскому полу
staff.subset(staff,"male")
##        name salary  sex weight height size
## a      Иван    500 male     82   1.75  XXL
## b   Алексей    600 male     87   1.80    S
## c Александр    400 male     93   1.90   XL
## f  Валентин    550 male     72   1.72    M
## g    Андрей   2000 male     82   1.85    L
#выведем данные по мужскому полу и отсортируем по зарплате
staff.subset(staff,"female","salary")
## mean of  salary  =  475
##      name salary    sex weight height size
## e Татьяна    300 female     NA   1.70    S
## d    Анна    650 female     NA   1.65    S
#то же, только зададим явно все имена аргументов
staff.subset(staff=staff,sex="female",var="salary")
## mean of  salary  =  475
##      name salary    sex weight height size
## e Татьяна    300 female     NA   1.70    S
## d    Анна    650 female     NA   1.65    S
#изменим порядок аргументов: третий аргумент (var) идет вторым
#в этом случае обязательно указывать название аргумента
staff.subset(staff,var="salary")
## mean of  salary  =  714.3
##        name salary    sex weight height size
## e   Татьяна    300 female     NA   1.70    S
## c Александр    400   male     93   1.90   XL
## a      Иван    500   male     82   1.75  XXL
## f  Валентин    550   male     72   1.72    M
## b   Алексей    600   male     87   1.80    S
## d      Анна    650 female     NA   1.65    S
## g    Андрей   2000   male     82   1.85    L
#второй аргумент следует первым
#остальные аргументы последовательно присваиваются оставшимся
staff.subset(sex="female",staff,"salary")
## mean of  salary  =  475
##      name salary    sex weight height size
## e Татьяна    300 female     NA   1.70    S
## d    Анна    650 female     NA   1.65    S
#последние два аргумента следуют первыми
#третий аргумент перенаправляется к первому неприсвоенному (staff)
staff.subset(var="salary", sex="female", staff)
## mean of  salary  =  475
##      name salary    sex weight height size
## e Татьяна    300 female     NA   1.70    S
## d    Анна    650 female     NA   1.65    S
#в качестве var зададим переменную weight (содержит пропущенные значения)
staff.subset(staff,var="weight") #среднее значение = NA
## mean of  weight  =  NA
##        name salary    sex weight height size
## f  Валентин    550   male     72   1.72    M
## a      Иван    500   male     82   1.75  XXL
## g    Андрей   2000   male     82   1.85    L
## b   Алексей    600   male     87   1.80    S
## c Александр    400   male     93   1.90   XL
## d      Анна    650 female     NA   1.65    S
## e   Татьяна    300 female     NA   1.70    S
#использование mean
staff$weight #переменная weight
## [1] 82 87 93 NA NA 72 82
mean(staff$weight) #без исключения пропущенных значений
## [1] NA
mean(staff$weight,na.rm=TRUE) #c исключением пропущенных значений
## [1] 83.2
#передадим параметр na.rm=TRUE через функцию staff.subset
staff.subset(staff,var="weight",na.rm=TRUE) # параметр na.rm перенаправляется в функцию mean
## mean of  weight  =  83.2
##        name salary    sex weight height size
## f  Валентин    550   male     72   1.72    M
## a      Иван    500   male     82   1.75  XXL
## g    Андрей   2000   male     82   1.85    L
## b   Алексей    600   male     87   1.80    S
## c Александр    400   male     93   1.90   XL
## d      Анна    650 female     NA   1.65    S
## e   Татьяна    300 female     NA   1.70    S

Generic-функции

#функция sd не является обобщенной - работает только для векторов
sd
## function (x, na.rm = FALSE) 
## sqrt(var(if (is.vector(x)) x else as.double(x), na.rm = na.rm))
## <bytecode: 0x0000000008dcd060>
## <environment: namespace:stats>
#функция str является обобщенной - UseMethod("str")
str
## function (object, ...) 
## UseMethod("str")
## <bytecode: 0x0000000007791790>
## <environment: namespace:utils>
#методы (реализации) функции str для раздичных типов данных
methods("str")
## [1] str.data.frame* str.Date*       str.default*    str.dendrogram*
## [5] str.logLik*     str.POSIXt*    
## 
##    Non-visible functions are asterisked

Библиотеки функций

attach(staff)
# просмотр  текущего окружения:
#рабочее пространство (".GlobalEnv")
#загруженные библиотеки(package:*)
#данные (staff)
search()
##  [1] ".GlobalEnv"        "staff"             "package:stats"    
##  [4] "package:graphics"  "package:grDevices" "package:utils"    
##  [7] "package:datasets"  "package:methods"   "Autoloads"        
## [10] "package:base"