class: center, middle, inverse, title-slide .title[ # Типы данных, условия, ввод и вывод ] .subtitle[ ## Визуализация и анализ географических данных на языке R ] .author[ ### Тимофей Самсонов ] .institute[ ### МГУ имени Ломоносова, Географический факультет ] .date[ ### 2024-09-03 ] --- # Типы данных Тип данных — это класс данных, характеризуемый членами класса и операциями, которые могут быть к ним применены. С помощью типов данных мы можем представлять привычные нам сущности, такие как числа, строки и т.д. В языке R существует 5 базовых типов данных: <br> Название | Тип данных ---------|----------- `complex` | комплексные числа `character`| строки `integer` | целые числа `logical` | логические (булевы) `numeric` | числа с плавающей точкой <!-- Помимо этого есть тип `Date`, который позволяет работать с датами. Рассмотрим использование каждого из перечисленных типов. --> --- # Числа Числа — основной тип данных в R. К ним относятся _числа c плавающей точкой_ и _целые числа_. Сложение и вычитание: ``` r 2 + 3 ## [1] 5 2 - 3 ## [1] -1 ``` Умножение и деление: ``` r 2 * 3 ## [1] 6 5 / 3 ## [1] 1.666667 ``` --- # Числа Целочисленное деление `%/%`: ``` r 5 %/% 3 ## [1] 1 ``` Остаток от деления `%%`: ``` r 5 %% 3 ## [1] 2 ``` Возведение в степень: ``` r 2 ^ 3 ## [1] 8 2 ** 3 ## [1] 8 ``` --- # Переменные Как правило, в настоящих программах числа в явном виде встречаются лишь иногда. Поскольку одно и то же число может выполнять разные функции в разных выражениях, в программе вводят переменные и присваивают им значения с помощью оператора `<-` либо `=`: ``` r a <- 5 b = 3 ``` Чтобы вывести значение переменной на экран, достаточно просто ввести его: ``` r a ## [1] 5 b ## [1] 3 ``` --- # Переменные .pull-left[ Мы можем выполнить над переменными все те же операции что и над константами: ``` r a + b ## [1] 8 ``` ] .pull-right[ Новую переменную можно создать на основе значений существующих переменных и констант: ``` r d = b e = a + d f = e + 2.5 d ## [1] 3 e ## [1] 8 f ## [1] 10.5 ``` ] --- # Переменные .pull-left[ Противоположное по знаку число получается добавлением унарного оператора `-` перед константой или переменной: ``` r f = -2 f ## [1] -2 f = -e f ## [1] -8 ``` ] .pull-right[ Операция взятия остатка от деления бывает полезной, например, когда мы хотим выяснить, является число четным или нет: ``` r d %% 2 ## [1] 1 e %% 2 ## [1] 0 ``` ] --- # Числовые функции .pull-left[ В качестве аргумента функции можно использовать переменную, константу, а также выражения: ``` r sqrt(a) ## [1] 2.236068 tan(1.5) ## [1] 14.10142 abs(a + b - 2.5) ## [1] 5.5 ``` ] .pull-right[ Вы также можете легко вкладывать функции одна в одну, и записывать результат в переменную: ``` r b = sqrt(sin(a) + 2) b ## [1] 1.020331 ``` ] --- # Строки Строки состоят из символов. Чтобы создать строковую переменную, необходимо заключить текст строки в кавычки: ``` r s = "В историю трудно войти, но легко вляпаться (М.Жванецкий)" s ## [1] "В историю трудно войти, но легко вляпаться (М.Жванецкий)" ``` Длину строки в символах можно узнать с помощью функции `nchar()` ``` r nchar(s) ## [1] 56 ``` --- # Строки _Конкатенация_ — сцепление строк — выполняется с помощью функции `paste()`: ``` r s1 = "В историю трудно войти," s2 = "но легко вляпаться" s3 = "(М.Жванецкий)" paste(s1, s2, s3) ## [1] "В историю трудно войти, но легко вляпаться (М.Жванецкий)" ``` Конкатенировать можно не только строки, но и числа: ``` r year = 1950 pop = 1850 s1 = "Максимальная численность населения в Детройте пришлась на" s2 = "год и составила" s3 = "тыс. чел" paste(s1, year, s2, pop, s3) ## [1] "Максимальная численность населения в Детройте пришлась на 1950 год и составила 1850 тыс. чел" ``` --- # Даты Для создания даты используется функция `as.Date()`. В качестве аргумента функции необходимо задать дату, записанную в виде строки: ``` r birth = as.Date('1986/02/18') birth ## [1] "1986-02-18" ``` Сегодняшнюю дату вы можете узнать с помощью специальной функции `Sys.Date()`: ``` r current = Sys.Date() current ## [1] "2024-09-03" ``` --- # Даты Вычитание дат дает интервал во времени: ``` r current - birth ## Time difference of 14077 days ``` Сложение даты и интервала дает новую дату: ``` r current + 40 ## [1] "2024-10-13" ``` --- # Логические Логические переменные возникают там, где нужно проверить условие. Переменная логического типа может принимать значение `TRUE` (истина) или `FALSE` (ложь). Для их обозначения также возможны более компактные константы `T` и `F` соответственно. Следующие операторы приводят к возникновению логических переменных: * _РАВНО_ (`==`) --- проверка равенства операндов * _НЕ РАВНО_ (`!=`) --- проверка неравенства операндов * _МЕНЬШЕ_ (`<`) --- первый аргумент меньше второго * _МЕНЬШЕ ИЛИ РАВНО_ (`<=`) --- первый аргумент меньше или равен второму * _БОЛЬШЕ_ (`>`) --- первый аргумент больше второго * _БОЛЬШЕ ИЛИ РАВНО_ (`>=`) --- первый аргумент больше или равен второму --- # Логические Пример логических операций: ``` r a = 1 b = 2 a == b ## [1] FALSE a != b ## [1] TRUE a > b ## [1] FALSE a < b ## [1] TRUE ``` --- # Логические Если необходимо проверить __несколько условий одновременно__, их можно комбинировать с помощью логических операторов. Наиболее популярные среди них: * _И_ (`&&`) - проверка истинности обоих условий * _ИЛИ_ (`||`) - проверка истинности хотя бы одного из условий * _НЕ_ (`!`) - отрицание операнда (истина меняется на ложь, ложь на истину) ``` r c=3 (b>a) && (c>b) ## [1] TRUE (a>b) && (c>b) ## [1] FALSE (a>b) || (c>b) ## [1] TRUE !(a>b) ## [1] TRUE ``` --- # Определение типа данных Определение типа данных осуществляется с помощью функции `class()`: ``` r class(1) ## [1] "numeric" class(0.5) ## [1] "numeric" class(1 + 2i) ## [1] "complex" class("sample") ## [1] "character" class(TRUE) ## [1] "logical" class(as.Date('1986-02-18')) ## [1] "Date" ``` --- # Преобразование типов данных Преобразование типов данных осуществляется с помощью функций семейства `as(d, type)`, где `d` — это входная переменная, а `type` — название типа данных, к которому эти данные надо преобразовать (см. таблицу в начале главы). Несколько примеров: ``` r k = 1 m = as(k, "character") m ## [1] "1" class(m) ## [1] "character" n = as(m, "numeric") n ## [1] 1 class(n) ## [1] "numeric" ``` --- # Преобразование типов данных Для функции `as()` существуют обертки (_wrappers_), которые позволяют записывать такие преобразования более компактно и выглядят как `as.<datatype>(d)`, где `datatype` --- название типа данных: ``` r m = as.character(k) m ## [1] "1" class(m) ## [1] "character" n = as.numeric(m) n ## [1] 1 class(n) ## [1] "numeric" d = as.Date('1986-02-18') d ## [1] "1986-02-18" class(d) ## [1] "Date" ``` --- # Преобразование типов данных Если преобразовать число c плавающей точкой до целого, то дробная часть будет отброшена: ``` r as.integer(2.7) ## [1] 2 ``` После преобразования типа данных к переменной будут применимы только те функции, которые определены для данного типа данных: ``` r a = 2.5 b = as.character(a) b + 2 ## Error in b + 2: non-numeric argument to binary operator nchar(b) ## [1] 3 ``` --- # Проверка типов данных и пустых значений Для проверки типа данных можно использовать функции семейства `is.<datatype>`: ``` r is.integer(2.7) ## [1] FALSE is.numeric(2.7) ## [1] TRUE is.character('Привет!') ## [1] TRUE ``` Особое значение имеют функции проверки пустых переменных (имеющих значение `NA` - not available), которые могут получаться в результате несовместимых преобразований или пропусков в данных: ``` r as.integer('Привет!') ## [1] NA ``` --- # Ввод данных c консоли Для ввода данных через консоль можно воспользоваться функцией `readline()`, которая будет ожидать пользовательский ввод и нажатие клавиши <kbd>Enter</kbd>, после чего вернет введенные данные в виде строки. Предположим, пользователь вызывает эту функцию и вводит с клавиатуры `1024`: ``` r a = readline() ``` Выведем результат на экран: ``` r a ## [1] "1024" ``` __Функция `readline()` всегда возвращает строку, поэтому если вы ожидаете ввод числа, полученное значение необходимо явным образом преобразовать к числовому типу__ --- # Вывод данных на консоль Для вывода данных в консоль можно воспользоваться тремя способами: - Просто напечатать название переменной с новой строки (_не работает при запуске программы командой `Source`_) - Вызвать функцию `print()` - Вызвать функцию `cat()` - Заключить выражение в круглые скобки `()` Функция `print()` работает точно так же, как и просто название переменной с новой строки, отличаясь лишь двумя особенностями: - `print()` явным образом говорит о том, что вы хотите вывести в консоль некую информацию - `print()` работает при любых методах запуска программы, в том числе методом `Source`. --- # Вывод данных на консоль ``` r a = 1024 a ## [1] 1024 print(a) ## [1] 1024 b = "Fourty winks in progress" b ## [1] "Fourty winks in progress" print(b) ## [1] "Fourty winks in progress" print(paste("2 в степени 10 равно", 2^10)) ## [1] "2 в степени 10 равно 1024" print(paste("Сегодняшняя дата - ", Sys.Date())) ## [1] "Сегодняшняя дата - 2024-09-03" ``` --- # Вывод данных на консоль Функция `cat()` отличается от `print()` следующими особенностями: - `cat()` выводит значение переменной, и не печатает ее измерения и внешние атрибуты. - `cat()` принимает множество аргументов и может осуществлять конкатенацию строк аналогично функции `paste()` - `cat()` не возвращает никакого значений, в то время как `print()` возвращает значение, переданное ей в качестве аргумента. - `cat()` можно использовать только для атомарных типов данных. Для классов (таких как Date) она будет выводит содержимое объекта, которое может не совпадать с тем, что пользователь ожидает вывести --- # Вывод данных на консоль ``` r cat(b) ## Fourty winks in progress cat("2 в степени 10 равно", 2^10) ## 2 в степени 10 равно 1024 cat("Сегодняшнаяя дата -", Sys.Date()) ## Сегодняшнаяя дата - 19969 ``` --- # Вывод данных на консоль Вывод с помощью круглых скобок позволяет выводить результат выполнения выражения: ``` r (a = rnorm(1)) # сгенерируем случайное число, запишем в переменную и выведем на экран ## [1] -0.2802329 (b = 2 * a) # переменная a доступна, ее можно использовать и далее для вычислений ## [1] -0.5604657 ``` --- # Условный оператор Проверка условий позволяет осуществлять так называемое ветвление в программе. Ветвление означает, что при определенных условиях (значениях переменных) будет выполнен один программный код, а при других условиях — другой. Для проверки условий используется условный оператор __if --- else if --- else__ следующего вида: ``` if (condition) { statement1 } else if (condition) { statement2 } else { statement3 } ``` --- # Условный оператор Например, сгенерируем случайное число, округлим его до одного знака после запятой и проверим относительно нуля: ``` r (a = round(rnorm(1), 1)) ## [1] -0.6 if (a < 0){ cat('Получилось отрицательное число!') } else if (a > 0) { cat('Получилось положительное число!') } else { cat('Получился нуль!') } ## Получилось отрицательное число! ``` --- # Условный оператор Условия часто нужны для обработки пользовательского ввода: ``` r cat('Введите широту вашей точки:') phi = as.numeric(readline()) ``` Пользователь вводит `68`, мы оцениваем результат: ``` r if (!is.na(phi)) { # проверяем, получилось ли преобразовать к числу if (abs(phi) >= 66.562 & abs(phi) <= 90) { # выполняем проверку на заполярность cat('Точка находится в Заполярье') } else { cat('Точка не находится в Заполярье') } } else { cat('Необходимо ввести число!') # оповещаем о некорректном вводе } ## Точка находится в Заполярье ``` --- # Оператор переключения Оператор переключения (switch) является удобен, когда надо сделать выбор на основе _конечного_ множества значений. Например, определим столицу Федерального округа по его названию: ``` r name = "Приволжский" capital = switch(name, 'Центральный' = 'Москва', 'Северо-Западный' = 'Санкт-Петербург', 'Южный' = 'Ростов-на-Дону', 'Северо-Кавказский' = 'Пятигорск', 'Приволжский' = 'Нижний Новгород', 'Уральский' = 'Екатеринбург', 'Сибирский' = 'Новосибирск', 'Дальневосточный' = 'Хабаровск') print(capital) ## [1] "Нижний Новгород" ```