-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathLab1.Rmd
More file actions
800 lines (588 loc) · 43.6 KB
/
Copy pathLab1.Rmd
File metadata and controls
800 lines (588 loc) · 43.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
---
title: Лабораторная работа 1. Введение в язык программировнания R и язык разметки RMarkdown
author: "Автор"
date: "10/02/2024"
output:
word_document: default
html_document:
df_print: paged
pdf_document:
latex_engine: lualatex
includes:
in_header: preamble.tex
---
# Язык разметки интерактивных блокнотов RMarkdown
[Краткое описание языка разметки](https://rmarkdown.rstudio.com/lesson-1.html)\
[Подсказка](https://www.markdownguide.org/basic-syntax/)
Для перехода к новому абзацу можно использовать пустую строку
или 2 пробела в конце текущей строки
или завершить строку обратной косой чертой\
Текст можно выделить *курсивом*, **жирным** или ***жирным курсивом***. Можно выделить верхний индекс A^2^, нижний индекс B~2~ и ~~зачеркнуть~~. Короткое тире -- и длинное тире ---
> Это цитата
Уровень заголовка задаётся символами #. После заголовка обязательна пустая строка.
# Заголовок 1
## Загловок 2
##### Заголовок 6
Маркированный список
- элемент 1
- элемент 1a (отступ 1 табуляция)
- элемент 2
Нумерованный список
1. Первый элемент
2. Второй элемент
3. Третий элемент
1. Первый подэлемент
2. Второй подэлемент
Уравнение заданное в тексте: $e^{i \pi} + 1 = 0$
Уравнение отдельным блоком: $$E = mc^{2}$$
| Правое | Левое | Стандратное | Центрирование |
|-------:|:------|-------------|:-------------:|
| 12 | 12 | 12 | 12 |
| 123 | 123 | 123 | 123 |
| 1 | 1 | 1 | 1 |
Код можно включить непосредственно в текст, он исполнится в момент генерации документа. Этот документ сгенерирован в версии языка R: `r getRversion()`.
Также код можно выделить в отдельный блок. Блок создаётся **Ctrl**+**Alt**+**I**. Вычислить строку в блоке **Ctrl**+**Enter**. Вычислить весь блок **Ctrl**+**Shift**+**Enter**
```{r}
1+1
```
Визуальное редактирование документа поддерживается в RStudio переключением режима из *Source* в *Visual*
# Базовые конструкции языка R
## Типы данных
В R все элементы, используемые для вычислений, называются объектами. Зарезервированы 5 atomic типов (классов) объектов:
```{r}
class(10.5)
class(100L)
class(9+3i)
class("1ac")
class(TRUE)
```
Базовый объект - вектор. Вектор может содержать объекты только одного типа.
```{r}
1
```
При объединении объектов разных типов в вектор, они приводятся к более широкому (implicit coercion)
```{r}
class(c(TRUE, FALSE))
class(c(1L, TRUE))
class(c(1L, 2L))
class(c(1L, 2.5))
class(c(1L, 2.5, 2.5+1i))
class(c(1L, 2L, 2.5+1i, "12"))
```
## Базовые операции
```{r}
x <- 3 # присвоение значения переменной, предпочтительно использовать
3 -> x # присвоение значения переменной
x <<- 3 # присвоение значения переменной из внешей области видимости
+3;2+3
-2;5-2
2*5
3/5
2^5; 2**10 # возведение в степень
10 %% 3 # остаток от деления
10 %/% 3 # целочисленное деление
```
## Логические операции
```{r}
x <- c(TRUE,FALSE,TRUE)
y <- c(FALSE,TRUE,TRUE)
x < 3
x <= y
2 > x
x >= x
3 == 5
3 != 5
!x # логическое отрицание
x & y # поэлементное логическое И
TRUE && FALSE # логическое И
x | y # поэлементное логическое OR
TRUE || FALSE # логическое ИЛИ
xor(x, y) # поэлементное логическое Исключающее ИЛИ
isTRUE(x) # явное приведение к логическому типу
```
## Встроенные константы
В R зарезервирован набор специальных констант:
- **Inf** -- *бесконечность*
- **NA** -- *Not Available*. Отсутствующее значение. Используется для обозначения пропущенных значений в данных.
- **NaN** -- *Not A Number*. Определяет неопределенное число или «не число».
- **NULL** -- представляет нулевой объект. Часто используется когда возвращаема величина выражения или функции не определена.
- **pi** -- *3.141593*
```{r}
pi/Inf
```
## Атрибуты объектов
Объекты характеризуются атрибутами которые могут быть рассмотрены, как метаданные для объектов. Не все объекты имеют атрибуты. Атрибуты используются для упрощения понимания и описания объектов. Примеры атрибутов объектов:
- names, dimnames
- dimensions
- class
- length
- прочие, определенные пользователем, атрибуты (metadata) Для доступа к атрибутам объекта используется функция **attributes**
```{r}
x <- cbind(a = 1:3, pi = pi)
x
attributes(x)
```
## Создание вектора элементов
Вектор может содержать объекты только одного типа. Вектор можно создать с помощью функций: - **с** -- combine - **seq** -- создание вектора последовательных чисел. - **vector** -- создание пустого вектора или вектора нулей - **rep** -- создание вектора, состоящего из одинаковых элементов. - **:** -- упрощенная форма seq
```{r}
vector(mode = "numeric", length = 2)
seq(1, 9, by = 2)
rep(1:3, 2)
1:10
```
## Преобразование объектов
Для преобразования объекта к другому типу используются функции семейства **as.\***
```{r}
as.logical(c(-1, 0, 1))
as.numeric(c(TRUE, FALSE))
as.character(c(TRUE, FALSE))
```
## Матрицы и массивы высших размерностей
Матрица -- это специальный тип вектора в R, который имеет атрибут *dim*. *dim* -- это вектор типа integer, состоящий из 2 элементов ( *nrow* - число строк и *ncol* - число столбцов). Матрицы заполняются по правилу: сверху вниз слева направо.
```{r}
m <- matrix(c(1, 2, 3, 4), ncol = 2, nrow = 2)
m
dim(m)
attributes(m)
```
Матрицы можно создавать с помощью функций **cbind** и **rbind**.
```{r}
x <- 1:3
y <- 10:12
cbind(x, y)
```
**array(data,dim)** -- функция для создания матрицы заданного размера.
```{r}
array(1:8,c(2,2,2))
```
## Cписки
Список (list) -- особый вид вектора, который объединяет объекты различных типов. **list** -- функция для объединения объектов в список.
```{r}
list(1,c(1,2),"abobus",TRUE)
```
## Факторы
Фактор (factor) -- специальный класс векторов, который предназначен для хранения кодов соответствующих уровней номинальных признаков. Фактор можно рассматривать как вектор типа integer, каждый элемент которого представляет метку класса. Однако для удобства понимания лучше использовать метки типа "Male" , "Female". **factor** -- функция для объединения объектов в фактор. Аргумент -- вектор типа character.
```{r}
x <- factor(c("yes", "yes", "no", "yes", "no"))
x
```
У переменной типа factor два атрибута *class* и *levels*, демонстрирующие тип объекта и метки категориальной переменной. **unclass** -- функция, используется для разложения фактора на составляющие элементы.
```{r}
attributes(x)
unclass(x)
```
Порядок уровней может быть задан аргументом *levels*.
```{r}
factor(c("yes", "yes", "no", "yes", "no"), levels = c("yes", "no"))
```
## Пропущенные значения
**NA**, **NaN** -- используются для работы с пропущенными значениями. **is.na** -- функция для проверки наличия в векторе элементов с пропущенными значениями типа **NA**. **NA** может иметь тип *integer*, *numeric*, *character*. **is.nan** -- функция для проверки наличия в векторе элементов с пропущенными значениями типа **NaN**.
```{r}
x <- c(1, NaN, NA, 10, 3)
is.na(x)
is.nan(x)
```
## Таблицы
Таблица (Data Frame)-- специальный тип списка, в котором каждый элемент имеет фиксированную длину. Используется для хранения табулированных данных. Каждая колонка может представлять различные типы данных, включая факторы. Data Frame имеют специализированный атрибут *row.names*, указывающий имена строк. Это помогает упростить аннотацию данных. Для создания Data Frame из табулированных данных используются функции **read.table** и **read.csv**. Для создания матрицы из Data Frame используется функция **data.matrix**. **data.frame** -- функция для создания Data Frame.
```{r}
x <- data.frame(foo = 1:4, bar = c(T, T, F, F))
nrow(x)
ncol(x)
```
## Имена
Имена (Names) -- используются для лучшего понимания объектов и написания программного кода. Элементы объектов могут иметь имена. **names** -- функция для присвоения имен элементам объектов.
```{r}
x <- 1:3
names(x)
names(x) <- c("foo", "bar", "norf")
names(x)
```
Списки и матрицы также могут иметь имена.
```{r}
list(a = 1, b = 2, c = 3)
m <- matrix(1:4, nrow = 2, ncol = 2)
dimnames(m) <- list(c("a", "b"), c("c", "d"))
m
```
## Управление наборами данных
### Доступ к элементам структур данных
В R используются несколько операторов для извлечения данных из объектов -- "**[**", "**[[**", "**\$**".\
"**[**" -- возвращает объект того же класса что и объект-оригинал. Пример -- из вектора -\> вектор, из списка -\> список и т.д. Может быть выделено **более 1** элемента!\
"**[[**" -- используется для взятия элемента списка или таблицы (Data Frame). Класс элемента может быть различным. Может быть выделен **только 1** элемент!\
"**\$**" -- применяется для выделения элемента списка или таблицы по имени name. Класс элемента не обязательно совпадает с исходными данными.
Примеры использования оператора "**[**"
```{r}
x <- c("a", "b", "c", "c", "d", "a")
x[1]
x[2]
x[1:4]
u <- x > "a"
u
x[u]
```
Доступ к элементам матриц осуществляется с использованием индексов в квадратных скобках -- "**[**". Первый индекс -- номер строки, второй индекс -- номер столбца.
```{r}
x <- matrix(1:6, 2, 3)
x[1, 2]
x[2, 1]
```
Первый или второй индекс может отсутствовать. Тогда будет возвращена строка или столбец матрицы.
```{r}
x[1, ]
x[, 2]
```
По умолчанию возвращается вектор единичной длины того же класса что и исходный объект. Для получения объекта в виде матрицы необходимо установить параметр *drop*. Учет размерности данных -- **drop = FALSE**.
```{r}
x <- matrix(1:6, 2, 3)
x[1, 2, drop = FALSE]
x <- matrix(1:6, 2, 3)
x[1, ]
x[1, , drop = FALSE]
```
### Доступ к элементам списка
Для доступа к элементам списка можно использовать -- "**[**", "**[[**", "**\$**".
```{r}
x <- list(foo = 1:4, bar = 0.6)
x[1]
x[[1]]
x$bar
x[["bar"]]
x <- list(foo = 1:4, bar = 0.6, baz = "hello")
x[c(1, 3)]
```
Оператор "**[[**" используется с индексами и именами, а "**\$**" - только с именами объектов. "**\$**" упрощает работу, т.к. не требуется определение порядка следования.
```{r}
x <- list(foo = 1:4, bar = 0.6, baz = "hello")
name <- "foo"
x[[name]]
x$name
x$foo
```
Оператор "**[[**" может принимать последовательность целых чисел и рекурсивно извлекать элементы из вложенного списка.
```{r}
x <- list(a = list(10, 12, 14), b = c(3.14, 2.81))
x[[c(1, 3)]]
x[[1]][[3]]
x[[c(2, 1)]]
```
### Частичное совпадение
Partial matching -- определение элемента по его первым буквам имени. Используется для операторов "**[[**", "**\$**" с целью сокращения программного кода.
```{r}
x <- list(abobus = 1:5)
x$a
x[["a"]]
x[["a", exact = FALSE]]
```
По умолчанию Partial matching работает для оператора "**\$**", но не работает для "**[[**". В последнем случае необходимо использовать параметр **exact = FALSE**.
Часто в ходе обработки данных необходимо найти и удалить из элементов объекта пропущенные значения типа **NA** или **NaN**. Процедура выполняется в два шага: 1) Создается логический вектор, указывающий на элементы с пропущенными значениями. 2) Из исходного объекта извлекаются «нормальные» элементы с помощью созданного логического вектора.
```{r}
x <- c(1, 2, NA, 4, NA, 5)
bad <- is.na(x)
x[!bad]
```
## Векторные операции
В R можно осуществлять операции над векторами. Это позволяет значительно упростить программный код, не программировать циклы, ускорить процесс написания программ.
```{r}
x <- 1:4
y <- 6:9
x + y
x > 2
x >= 2
y == 8
x * y
x / y
```
Аналогично векторные операции осуществляются над матрицами.
```{r}
x <- matrix(1:4, 2, 2);
y <- matrix(rep(10, 4), 2, 2)
x * y # поэлементно
x / y
```
Оператор "%\*%" используется для матричное перемножение по правилам линейной алгебры.
```{r}
x %*% y
```
## Чтение и запись данных
Для чтения данных в R используются несколько базовых функций:
- **read.table**, **read.csv** -- чтение табулированных данных
- **readLines** -- чтение текстовых строк из файла
- **source** -- загрузка в активное пространство памяти R--кодов (функции)
- **dget** -- загрузка в активное пространство памяти одиночных R--объектов из (ASCII) текстовых файлов R
- **load** -- загрузка объектов рабочего пространства
- **unserialize** -- чтение одиночных R--объектов в бинарном формате
Для записи данных используются функции:
- **write.table** -- запись табулированных данных
- **writeLines** -- запись текстовых строк в файла
- **dump** -- запись R--объектов в текстовый файл
- **dput** -- запись одиночных R--объектов в текстовый файл
- **save** -- запись объектов рабочего пространства
- **serialize** -- запись одиночных R--объектов в бинарном формате
### Read.table
read.table(file, header, ...) одна из основных функций чтения небольших табулированных данных. Рассмотрим основные управляющие аргументы функции:
- *file* -- служит для указания пути к импортируемому файлу. Пример -- *file* = "c:/Temp/MyData.dot" . В качестве имени файла можно указать URL-ссылку.
- *header* -- логический индикатор, указывает является ли первая строка заголовком (названия колонок таблицы). По умолчанию *header* = FALSE.
- *sep* -- указывает на символ разделения между колонками. По умолчанию *sep* = " ". Для файлов .csv *sep* =",".
- *colClasses* -- вектор типа character, длина вектора равна количеству колонок данных, содержимое определяет типы данных в колонках.
- *nrows* -- определяет число строк, которое должно быть считано из файла.
- *comment.char* -- указывает, что является символом, после которого идет текст комментария.
- *skip* -- указывает на число строк от начала файла, которые должны быть пропущены при чтении данных.
- *stringsAsFactors* -- логический флаг, указывает, надо ли перевести символьные переменные в данные типа **factor**. По умолчанию *stringsAsFactors* = TRUE.
Для небольших наборов данных рекомендуется использовать read.table с параметрами по умолчанию. В результате выполнения функции: - *data* имеет структуру **Data Frame** - Автоматически пропускаются строки после **\#** - Автоматически определятся типы колонок данных. Однако для ускорения работы рекомендуется определять типы данных напрямую.
**read.csv** работает аналогично **read.table**, за исключением того, что разделитель колонок -- запятая. Подобные файлы предоставляются программами типа MS Excel.
Для работы с текстовыми данными (не табулированными) используются функции **dput**, **dget**. Преимущество хранения данных в текстовом формате -- их можно редактировать. В случае повреждения имеют высокий потенциал восстановления. Файлы содержат метаданные.
```{r}
y <- data.frame(a = 1, b = "a")
dput(y)
dput(y, file = "y.R")
```
```{r}
dget("y.R")
```
Функция **dump** позволяет записывать сразу несколько объектов. Для восстановления объектов из текстовых файлов используется функция **source**.
```{r}
x <- "foo"
y <- data.frame(a = 1, b = "a")
dump(c("x", "y"), file = "data.R")
rm(x, y)
source("data.R")
y
```
### Функции установления соединений с внешними источниками данных
Существует несколько альтернативных способов для установления соединения (connection) с внешними источниками данных. - **file** -- создать связь с файлом (стандартный несжатый файл). - **gzfile** -- создать связь с файлом, сжатым с gzip. - **bzfile** -- создать связь с файлом, сжатым с bzip2. - **url** -- открыть связь с web-страницей. \### file
- *description* -- имя файла.
- *open* -- тип работы с кодом файла.
- "r" -- только для чтения.
- "w" -- только для записи и создания нового файла.
- "a" -- добавление (appending).
- "rb", "wb", "ab" -- по аналогии для бинарных файлов.
Создание файла для дальнейших действий
```{r}
fileConn <- file("output.txt")
writeLines(c("Hello,1","World,2"), fileConn)
close(fileConn)
```
connection позволяет упростить работу с большими файлами, когда нет необходимости загружать весь исходный файл данных.
```{r}
con <- file("output.txt", "r")
data <- read.csv(con)
data
close(con)
```
### readLines
В режиме connection можно использовать функцию **readLines** для чтения заданного количества строк из файлов.
```{r}
con <- file("output.txt")
readLines(con,2)
```
## Функции
Функции используются для систематизации повторяющегося программного кода. Функция создается с помощью оператора **function** и сохраняется как R-объект класса *function*.
Особенности: 1. Объекты класса function можно передавать в качестве аргумента другой функции. 2. Функции могут быть вложенными, т.е. одна функция может быть определена внутри другой. 3. Возвращаемое значение функции -- это результат последнего выражения в коде функции.
Аргументы сопоставляются по позициям в списке или по совпадению имен.
```{r}
mydata <- rnorm(100)
sd(mydata)
sd(x = mydata)
sd(x = mydata, na.rm = FALSE)
sd(na.rm = FALSE, x = mydata)
sd(na.rm = FALSE, mydata)
```
### Сопоставление аргументов
Если передаются именованные аргументы, то их не обязательно располагать в требуемом порядке. Можно смешивать «порядок» и «имена». Именованный аргумент извлекается из списка, остальные будут ассоциированы по позициям оставшихся аргументов в списке.
```{r}
args(lm)
```
Имена аргументов могут совпадать не полностью, а частично. Система сама определяет наиболее подходящий аргумент и присваивает ему значение. Порядок следования операций определения аргументов в функциях: 1) Проверка на точное совпадение именованных аргументов. 2) Проверка на частичное совпадение именованных аргументов. 3) Проверка на точное совпадение позиций неименованных аргументов.
```{r}
f <- function(a, b = 1, c = 2, d = NULL) {
return(1);
}
```
Аргумент функции в виде "..." используется для передачи стандартных аргументов сторонних функций.
```{r}
myplot <- function(x, y, type = "l", ...) {
plot(x, y, type = type, ...)
}
```
Аргумент "..." применяется когда число аргументов функции заранее не известно
```{r}
args(paste)
args(cat)
```
Аргументы, идущие после "...", должны быть именованы полностью.
```{r}
args(paste)
paste("a", "b", sep = ":")
paste("a", "b", se = ":")
```
## Векторизированные вычисления
Использование операторов циклов **for**, **while** не удобно при работе в командной строке интерпретатора. В R реализованы функции, оптимизирующее циклически вычисления:\
- **lapply** -- производит циклическое вычисление некоторой функции над элементами списка. - **sapply** -- выполняет то же что **lapply**, только выводит результаты в упрощенном виде. - **apply** -- производит циклическое вычисление некоторой функции над элементами массива. - **tapply** -- производит циклическое вычисление некоторой функции над заданным набором элементов вектора. - **mapply** -- мультивариативная версия функции **lapply** (работает сразу с несколькими объектами).
**lapply** производит циклическое вычисление некоторой функции над элементами списка. **lapply** всегда возвращает объект класса список, несмотря на тип объекта на входе. Если объект на входе не список, то он будет преобразован с помощью функции **as.list**.
**sapply** вариант функции **lapply**, предназначенный для максимального упрощения результатов. Например: 1. Если результат список (list), каждый элемент которого имеет длину 1, то возвращается вектор. 2. Если результат список (list), каждый элемент которого вектор одинаковой длины, то возвращается матрица.\
3. Если результат непонятно как может быть преобразован, то возвращается список.
**apply** используется для вычисления некоторой функции в пределах заданного набора индексов массива. Особенности: 1. В основном применяется для вычисления некоторой функции по строкам или столбцам массива. Работает даже для трехмерных матриц. 2. Используется для массивов любой размерности.
**mapply** -- мультивариативный вариант **lapply** и **sapply**, предназначенный для параллельного применения в цикле некоторой функции к набору R-объектов.
Пример векторизации функции.
```{r}
rnorm (5, 1, 2)
mapply(rnorm, 1:5, 1:5, 2)
```
**tapply** -- используется для расчета некоторой функции в цикле по группам элементов вектора. Это удобно когда один вектор формирует несколько выборок.
## Правила видимости свободных переменных (Scoping rules)
```{r eval=FALSE, include=FALSE}
lm <- function(x) { x * x }
lm
```
Для присвоения **lm** некоторого значения будет осуществляться поиск данной функции в различных областях или пространствах памяти среды -- environments. Environment -- список или набор R-объектов (по типу символ-значение), которые представляют собой видимое по некоторым правилам пространство памяти. Если работа производится в строке интерпретатора команд, то загружается global environment. В global environment входят все элементы, созданные или загруженные в R. При поиске **lm** порядок просмотра environments 1. global environment 2. пространства, загруженных пакетов (namespaces).
global environment эквивалентно пространству памяти «пользователя». После просмотра global environment поиск осуществляется от пространства памяти пакета stats к пространству пакета base. Порядок следования пакетов важен! **library** -- функция для загрузки пакетов. Загруженный пакет становится на вторую позицию, остальные пакеты смещаются на одну позицию вниз. Scoping rules определяют правила присвоения значений свободным переменным функций. В R используется lexical или static scoping. Наиболее распространенная альтернатива - dynamic scoping. Фактически задача сводится к вопросу: как R просматривает environments, для того чтобы связать свободную переменную с конкретным значением.
```{r}
z <- 1
f <- function(x, y) {
x^2 + y / z
}
```
Где *z* -- свободная переменная (a free variable). Свободная переменная не является ни формальным аргументом функции, ни локальной переменной функции.
## Scoping rules
**Правило (lexical rules) 1:** Значение для свободной переменной функции определяются в том пространстве памяти (environment), где была создана данная функция. Каждое environment имеет родительское environment. Родитель может иметь несколько потомков. Пространство без родителя называется пустым (empty environment). Функция + ее пространство памяти = closure или function closure. **Правило (lexical rules) 2:** Если значение для свободной переменной функций не найдено в пространстве, где была создана данная функция, то продолжается поиск по линии родительских пространств вплоть до пространства наивысшего уровня top-level environment (global environment или namespace of package). **Правило (lexical rules) 3:** После просмотра пространства наивысшего уровня (top-level environment) поиск осуществляется вниз по списку пространств загруженных пакетов (namespaces).
При достижении пространства последнего пакета (empty environment) в списке и не нахождения значения для свободной переменной выводится сообщение об ошибке.
```{r}
make_power <- function(n) {
pow <- function(x) {
x^n
}
return(pow)
}
cube <- make_power(3)
square <- make_power(2)
cube(3)
square(3)
```
Для просмотра пространства памяти функции можно воспользоваться функциями **ls**, **environment** и **get**.
```{r}
ls(environment(cube))
get("n", environment(cube))
```
```{r}
y <- 10
f <- function(x) {
y <- 2
y^2 + g(x)
}
g <- function(x) {
x*y
}
```
Достоинства lexical scoping: 1) Не требуется передача длинных списков аргументов в функции. Это значительно упрощает работу пользователя в интерактивном режиме и в ходе исследовательской (exploratory) работы. 2) Сокращает, а значит и упрощает, программный код. 3) Удобно для решения задач оптимизации (**nlm**, **optim** , **optimise**) для управления целевыми функциями, параметры которых обеспечивают корректное решение задачи.
## Поиск и исправление ошибок в программном коде (debugging)
В случае некорректной работы программы R может вывести 3 типа сообщений. - *message* -- общее сообщение диагностического характера, говорит о том, что что-то случилось. Не останавливает работу программы, печатает текст сообщения на экране. - *warning* -- сообщение о том, что что-то идет не так, но не фатально. Работа программы не прерывается. Сообщение выводится после завершения работы программы. - *error* -- сообщение о появлении фатальной ошибки в программе. Работа программы прерывается.
В R реализованы следующие интерактивные функции отладки программного кода: - **traceback** -- выводит на экран стек обращений к функциям, после того как произошла ошибка. - **debug** -- включает режим отладки для заданной функции, позволяет построчно пройти программу. Открывает специальную среду редактирования browse. - **browser** -- приостанавливает выполнение функции в строке, где напечатано **browser()**, и продолжает работать в режиме *debug* (среда редактирования browse). - **trace** -- позволяет вставить debugging code в код функции. - **recover** -- используется для модификации правила появления ошибки.
Загрузка, визуализация, анализ, предсказание на основе данных о компьютерных сетях
# Визуализация
Для построения интерактивных графиков используется современная библиотека plotly. Устанавливается командой *install.packages("plotly")*. Стоит выделить отличный от стандартного синтаксис вызова функции посторения графика. Строка "*x = ~x" означает, что в качестве значений оси X (слева от знака равенства) будут использоваться значения заданные формулой (оператор~* ). Сама формула *\~x* задаёт связь между зависимой переменной (слева от знака равенства, здесь опущенна) и независимыми. Например, в данном случае допустима конструкция *x = \~x + y*.
```{r}
library(plotly)
x <- seq(0, 2*pi, length.out=100)
y <- sin(x)
data <- data.frame(x, y);
plot_ly(data, x= ~x, y=~y,type = 'scatter', mode = 'lines')
```
Для построения объемного графика требуется построить матрицу значений функции с помощью функции **outer**.
```{r}
x <- y <- seq(0, pi/2, length.out = 100)
z <- outer(x, y, FUN = function(x,y) { sin(x*y) })
plot_ly(z = ~z) |> add_surface()
```
Контурный график
```{r}
x <- y <- seq(0, pi/2, length.out = 100)
z <- outer(x, y, FUN = function(x,y) { sin(x*y) })
plot_ly(x=x, y=y, z=z, type="contour")
```
# Дополнительные материалы
## Элементы функционального программирования
```{r}
library(purrr)
1:10 |> map(function(x) rnorm(10, x))
```
# Пример
Чтобы попасть из пункта А (остановка автобуса) в пункт В (лодочная станция) человек должен пройти сначала по асфальтовой дороге шириной *S* (отрезок Ах), а затем по песчаному пляжу шириной s (отрезок хВ). Скорость передвижения по асфальту V , скорость передвижения по песку v . Спрашивается, в каком месте нужно свернуть с асфальтовой дороги, чтобы затратить меньше времени на путь.
Реализуем задачу с конкретными значениями, в виду сложности аналитического решения (сводится к уравнению 4 степени): $D = 100$, $S = 40$, $V = 5$, $s = 60$, $v = 3$
```{r include=FALSE}
D <- 100
road_h <- 40
sand_h <- 60
v_sand <- 3
v_road <- 5
```
```{r echo=FALSE}
x <- seq(0,10, length.out = 1000)
# create data
aval <- list()
n <- 11
x_par <- seq(1, D-1, length.out = n)
for(step in 1:n)
{
road_x <- seq(0, x_par[step], length.out = 100);
road_y <- road_h/x_par[step]*road_x;
sand_x <- seq(x_par[step], D, length.out = 100);
sand_y <- road_h + sand_h/(D - x_par[step])*(sand_x-x_par[step]);
aval[[step]] <- list(visible = FALSE,
name = paste0(step),
road_x = road_x,
road_y = road_y,
sand_x = sand_x,
sand_y = sand_y)
}
aval[3][[1]]$visible = TRUE
# create steps and plot all traces
steps <- list()
fig <- plot_ly()
for (i in 1:n) {
fig <- add_lines(fig, x = aval[[i]]$road_x, y = aval[[i]]$road_y, visible = aval[[i]]$visible,
name = aval[[i]]$name, type = 'scatter', mode = 'lines', hoverinfo = 'name',
line=list(color='00CED1'), showlegend = FALSE)
fig <- add_lines(fig, x = aval[[i]]$sand_x, y = aval[[i]]$sand_y, visible = aval[[i]]$visible,
name = aval[[i]]$name, type = 'scatter', mode = 'lines', hoverinfo = 'name',
line=list(color="red"), showlegend = FALSE)
step <- list(args = list('visible', rep(FALSE, 2*n)), method = 'restyle', label = paste0(x_par[i]))
step$args[[2]][2*i] = step$args[[2]][2*i - 1] = TRUE
steps[[i]] = step
}
# add slider control to plot
fig <- fig %>%
layout(yaxis = list(range = c(-1,D + 1)),
xaxis = list(range = c(-1,D + 1)),
sliders = list(list(active = 3,
currentvalue = list(prefix = "x = "),
steps = steps)),
shapes = list(list(type = "rect", fillcolor = "red", line = list(color = "red"), opacity = 0.2, y0 = 0, y1 = road_h, x0 = 0, x1 = D),
list(type = "rect", fillcolor = "blue", line = list(color = "blue"), opacity = 0.2, y0 = road_h, y1 = D, x0 = 0, x1 = D)))
fig
```
Критерий оптимальности задается функцией $t(x)$, которую надо минимизировать, изменяя варьируемый параметр $х$. Остальные параметры задачи $(v,V,D,s,S)$ являются фиксированными. $$
t(x) = \frac{\sqrt{x^2+S^2}}{V} + \frac{\sqrt{(D-x)^2+s^2}}{v}
$$ $$
\begin{cases}
\min{t(x)} - ?\\
\frac{dt}{dx}=0\\
\frac{d^2t}{dx^2}>0
\end{cases}\,
$$ $$
t'(x)=\frac{x}{V \sqrt{S^2+x^2}}-\frac{d-x}{v \sqrt{(d-x)^2+s^2}}
$$
График целевой функци $t(x)$
```{r}
x <- seq(0, D, length.out=100)
y <- sqrt(x^2+road_h^2)/v_road + sqrt((D-x)^2+sand_h^2)/v_sand
data <- data.frame(x, y);
plot_ly(data, x= ~x, y=~y,type = 'scatter', mode = 'lines')
```
График производной целевой функци $t'(x)$
```{r}
x <- seq(0, D, length.out=100)
y <- x/(v_road*sqrt(road_h^2+x^2)) - (D-x)/(v_sand*sqrt(sand_h^2+(D-x)^2))
data <- data.frame(x, y);
plot_ly(data, x= ~x, y=~y,type = 'scatter', mode = 'lines')
```
Следовательно оптимальное значение пути, пройденного по дороге $x = 65.64$