Презентацию к лекции 11 Вы можете скачать здесь.
Векторы и базовые типы данных
Числовые векторы создаются с помощью функции c() (от англ. combine — комбинировать). В них можно записывать числа с плавающей точкой, целые числа или результаты функций. Запись 0x... используется для шестнадцатеричных чисел.
По умолчанию числовые векторы имеют тип double (число с плавающей точкой двойной точности). Даже вектор из одного числа, например 1, будет иметь тип double. Чтобы создать вектор целочисленного типа integer, используется запись с двоеточием, например, 1:5.
Комплексные числа записываются в формате действительная_часть + мнимая_частьi. Если действительная часть равна нулю, её всё равно нужно указать явно: 0 + 3i.
Предельная точность для чисел в R ограничена: максимальное значение — около 2 в степени 1024. Из-за особенностей хранения чисел с плавающей точкой вычисления могут давать погрешность на уровне ±1.
Текстовые (буквенные) векторы состоят из элементов типа character. Текст заключается в одинарные ('текст') или двойные ("текст") кавычки. Если один тип кавычек используется для внешнего обрамления, второй можно свободно использовать внутри. Для включения в строку кавычки того же типа, что и внешняя, перед ней ставится обратный слэш \.
Символы
Символы — это объекты языка, имена переменных и функций. Имя символа должно начинаться с буквы и может содержать точки, другие буквы, цифры и символ подчёркивания.
Важно: точка в имени символа — это просто часть имени, а не оператор доступа к методам, как в других объектно-ориентированных языках.
Если имя содержит недопустимые символы, его можно заключить в обратные кавычки (`). Это также позволяет получить доступ к телу функции, например, `+`.
Используя обратные кавычки, можно создавать новые, даже нелогичные символы. Например, можно выполнить `2+2` <- TRUE, и символ 2+2 будет содержать значение TRUE.
Однако существует список зарезервированных символов, которые нельзя переопределить. К ним относятся все операторы, управляющие конструкции и ключевые слова, такие как TRUE, FALSE, NULL и другие.
Операторы
Операторы — это функции со специальной формой записи. Они бывают:
- Унарные: оператор перед аргументом (
-x).
- Бинарные: оператор между двумя аргументами (
a + b).
- Тернарные: оператор с тремя аргументами.
Можно определять собственные операторы, заключая их имена в знаки процента: %оператор%.
Если оператор не определён для какого-то типа данных, язык попытается автоматически привести типы. Например, при применении унарного минуса к логическому вектору, TRUE будет преобразовано в 1, а FALSE — в 0.
Стандартные операторы включают: +, *, %% (остаток от деления), ^ (возведение в степень), %/% (целочисленное деление). Вызов функции — это тоже бинарный оператор, где первый аргумент — имя функции, а второй — её аргумент.
Все операции выполняются в порядке приоритета. Посмотреть приоритеты можно функцией ?Syntax. В общем виде порядок такой: сначала вызов функции и группировка, затем индексация, арифметические операции, сравнение, формулы и присваивание.
Присваивание
Присваивание — это связывание объекта с символом. Существуют три эквивалентных оператора присваивания:
<- (стрелка влево)
-> (стрелка вправо)
= (знак равенства, эквивалентен <-)
Можно присваивать значения элементам векторов, матриц и списков. Также существует "присваивание с модификацией". Например, определив функцию f <- function(x) x - 1, мы можем использовать запись f(length(s)) <- 3. Это эквивалентно length(s) <- f(3), то есть length(s) <- 2.
Группировка выражений
Выражения могут отделяться друг от друга переводом строки или точкой с запятой. Группа выражений в фигурных скобках {} рассматривается как одно. В этом случае выполняется весь код, но возвращается только результат последнего выражения.
Управляющие конструкции
Условный оператор if
Условный оператор if является функцией. Первый аргумент — условие — не должен быть вектором. Если передать в условие вектор, if возьмёт только его первый элемент, а остальные проигнорирует. Язык выдаст предупреждение.
Для векторных операций существует функция ifelse(условие, да, нет). Она принимает вектор условий и возвращает вектор, выбирая элементы из второго или третьего аргумента в зависимости от того, является ли соответствующее условие истинным или ложным.
Конструкция выбора switch
Конструкция выбора switch позволяет выбрать одно из нескольких выражений на основе значения первого аргумента. Если переданное значение не совпадает ни с одним из указанных вариантов, возвращается значение по умолчанию (последний безымянный аргумент).
Циклы
Циклы бывают трёх видов:
- repeat: бесконечный цикл, выход из которого осуществляется только оператором
break.
- while (условие): цикл с предусловием.
- for (переменная in вектор): цикл по элементам вектора.
Все эти циклы изменяют переменные в своём окружении. Для перехода к следующей итерации используется оператор next.
Доступ к структурам данных
Существует четыре основных способа доступа к элементам структур данных:
- Одиночные квадратные скобки
[] используются для векторов и списков. Индекс может быть числовым или символьным вектором, что позволяет извлекать подмножество элементов.
- Двойные квадратные скобки
[[]] используются для извлечения ровно одного элемента. Допускается частичное совпадение имён, если указана опция exact = FALSE.
- Оператор
$ используется для обращения к элементу списка по его имени.
- Оператор
@ используется для доступа к свойствам объектов класса S4.
Для практики рекомендуется обратиться к книге Джозефа Адлера "R in a Nutshell" или к онлайн-тренажёру Try R на сайте Code School.
Краткие итоги
Понимание синтаксиса языка программирования сродни изучению грамматики: сами по себе правила могут казаться абстрактными, но именно они определяют, насколько точно и свободно вы сможете выражать свои мысли, то есть — писать код. Изложенный материал последовательно выстраивает эту грамматическую основу для языка R, акцентируя внимание не просто на перечислении конструкций, а на логике их работы и внутренних взаимосвязях.
Ключевая идея, проходящая через весь материал, — это векторная природа R. Многие операции, которые в других языках являются скалярными, здесь по умолчанию применяются к векторам целиком. Это кардинально меняет подход к написанию кода, делая его более лаконичным и эффективным, но требуя понимания того, как работают типы данных и операторы с целыми структурами. Различие между типами double и integer, а также особенности работы с комплексными числами и строками, формируют базовое понимание того, как R хранит информацию.
Особое внимание уделяется гибкости языка. Возможность определять собственные операторы, переопределять символы и создавать функции для модифицирующего присваивания демонстрирует, что R — это не просто инструмент для статистических расчётов, а полноценная, расширяемая среда программирования. Понимание правил группировки выражений и порядка операций критически важно для написания предсказуемого и корректного кода.
Наконец, ясное представление о невекторной природе условного оператора if и о том, как ifelse решает эту проблему, уберегает от типичных ошибок новичков. Знание же о том, что циклы repeat, while и for предназначены для изменения внешних переменных, помогает выбрать правильный инструмент для итеративных задач. В совокупности, эти знания позволяют не просто копировать примеры, а осознанно конструировать собственные решения для обработки и анализа данных, эффективно используя парадигму языка R.
1. Векторы — фундаментальная структура данных в R, а функция c() — основной способ их создания.
2. По умолчанию числа имеют тип double, а для создания целочисленного типа (integer) необходимо использовать оператор :.
3. Символы в R могут быть практически любыми, если их заключить в обратные кавычки, что даёт языку большую гибкость.
4. Операторы — это функции со специальным синтаксисом, и пользователь может определять свои собственные.
5. Порядок выполнения операций строго определён и его можно проверить с помощью встроенной документации (?Syntax).
6. Существует три эквивалентных способа присваивания: <-, -> и =.
7. Присваивание с модификацией (например, f(x) <- value) — мощный инструмент для лаконичного изменения объектов.
8. Условный оператор if не векторизован, в то время как функция ifelse предназначена для работы с векторами условий.
9. Циклы repeat, while и for предназначены для выполнения повторяющихся действий и изменения переменных в своём окружении.
10. Способы доступа к данным ([], [[]], $, @) предоставляют гибкие инструменты для извлечения как одиночных элементов, так и подмножеств.
1. Какой тип данных получится в результате выполнения typeof(1) и почему?
2. Каким образом можно записать строку, содержащую одинарную кавычку, если сама строка заключена в одинарные кавычки?
3. В чём ключевое отличие роли точки в именах символов в R от её роли в других объектно-ориентированных языках?
4. Каким образом можно переопределить существующий или создать новый оператор?
5. Что произойдёт при применении оператора - к логическому вектору c(TRUE, FALSE)?
6. Почему оператор = считается эквивалентным оператору <-?
7. Объясните механизм работы «присваивания с модификацией» на примере функции f и length(s).
8. Что вернёт группа выражений, заключённая в фигурные скобки, если в ней несколько строк?
9. Почему конструкция if (c(TRUE, FALSE)) { ... } считается некорректной и как сделать её векторной?
10. В чём принципиальное различие между циклом repeat и циклами while и for?
11. Какой оператор используется для доступа к свойству объекта класса S4?
12. В чём разница между извлечением элемента с помощью [] и [[]] из списка?