Розділ 2 Базові конструкції мови R: типи та структури даних. Частина 1


2.1 Оголошення та ініціалізація змінних

2.1.1 Поняття змінних та оператор присвоєння

Базовим поняттям практично усіх мов програмування є змінна. Змінна дозволяє записати значення або об’єкт та назвати його для подальшого доступу, зміни, видалення по імені.

Наприклад, присвоєння змінній my_variable значення 10 записується так: my_variable <- 5 або my_variable = 5.

Операція надання змінній певного значення у програмуванні називається присвоєнням.

Важливо! Зверніть увагу, що присвоєння (<-, =) та рівність (==) це різні поняття. Оператор == здіснює перевірку співпадіння значення двох змінних/об’єктів та повертає результат у вигляді логічного значення TRUE (якщо значення рівні) або FALSE (якщо значення не рівні).

Знак <- не є часто використовуваним у різних мовах програмування, зазвичай для присвоєння користуються =. Проте в R освновним способом засобом початкової ініціалізації змінних є <-.

Також у програмуванні на R використовуються оператори присвоєння <<-, ->, ->>. Про них можна прочитати за лыками нижче.

Рекомендую почитати про різницю між операторами присвоєння у R <- та = тут:

  1. Why do we use arrow as an assignment operator? (Colin FAY).
  2. Difference between assignment operators in R (Ren Kun).
  3. Assignment Operators.

Приклад:

x <- 45
y <- 10
z <- x + y # z = 45 + 10
z
## [1] 55

Розберемо приклад, описаний вище:

  • У першому рядку оголошується змінна x і їй присвоюється значення 45.
  • У другому рядку оголошується змінна y і їй присвоюється значення 10.
  • У третьому рядку оголошується змінна z і їй присвоюється значення суми x + y.
    # у R використовується як коментар коду, текст написаний після нього ігнорується.
  • У четвертому рядку відбувається виведення на консоль змінної z.

2.1.2 Правила іменування змінних

Є кілька основних правил іменування змінних у R: 1. Ім’я змінної може складатися з букв [a-z, A-z], цифр [0-9], крапки . та нижнього підкреслювання _. 2. Ім’я змінної повинно починатися з букви або крапки. Якщо воно починається з крапки, то наступним символом повинна бути буква. 3. Не можна використовувати зарезервовані ключові слова мови програмування для іменування змінних, наприклад, TRUE/FALSE.

Ім’я змінної не може містити пробіл (space). Якщо є потреба назвати об’єкт кількома словами, то їх зазвичай розділяють підкресленням _ або крапкою .. Наприклад, змінну можна назвати my_variable_name або my.variable.name. Назва myVariableName (camel case) теж буде коректно сприйнята мовою програмування R, проте такий запис тут вживається не часто.

Приклад коректного іменування змінних: total, zminna, Sum, .length_of_something, Number123, x_1.

Приклад неправильного іменування змінних: tot@l, 5x_1, _variable, FALSE, .0ne.

2.2 Базові типи даних

2.2.1 Типізація в R

Усі мови програмування мають власну типізацію даних з якими працюють. Тип даних - це набір властивостей певних об’єктів та операцій, що можна з ними виконувати. Так, наприклад, з цілими числами можна виконувати арифметичні операції додавання, віднімання та інші. Набори символів (простими словами текст) зазвичай можуть використовуватися для пошуку у них елементів, редагування (шляхом видалення частини існуючого або додавання нового тексту), склеювання та розділення на частини.

У R, на відміну від строго типізованих мов програмування, тип даних визначається на основі поточного значення елемента і може змінюватися у процесі виконання.

Розгялнемо приклад коду з мови програмування C# (мова родом із C/Java):

int a = 10;
a = "some text";

Подібний код у C# передбачає створення нової змінної a типу int (integer - ціле число), а потім відбувається присвоєння для a текстового фрагмента (тип string у С#). Такий код не буде запущено і виникне помилка компіляції.

Розглянемо приклад коду з R:

a <- 10
a <- "some text"
a
## [1] "some text"

Такий код виконається і на консоль буде виведено some text, адже у 1 першому рядку було присвоєно ціле число, у другому - текст. Таким чином R має динамічну типізацію, що дозволяє у ту ж саму змінну записати значення різних типів. Проте варто пам’ятати, що попереднє значення буде втрачено.

До базових типів даних у R варто віднести:

  • Числа з дробовою частиною (decimal numbers), як наприклад, 4.0, 15.214, що називаються numeric(s).
  • Натуральні числа (natural numbers), як наприклад, 4, 15, що називаються integer(s).
  • Логічні значення (boolean values), тобто TRUE та FALSE (які також можна скорочено записувати T та F), що називаються logical.
  • Текст або рядки (string values), як наприклад, "Hello", "12 is number", що називаються character(s).

Оголосимо для прикладу три змінні: my_numeric - число, my_character - текст, my_logical - логічне значення.

my_numeric <- 5
my_character <- "universe"
my_logical <- FALSE

Замінимо значення my_character <- "5" та спробуємо знайти суму значень:

my_character <- "5"
my_sum <- my_numeric + my_character

У результаті виклання даного коду ми отримаємо помилку, адже значення 5 та "5" є елементами різних типів даних, перевіримо типи за допомогю функції class():

class(5)
## [1] "numeric"
class("5")
## [1] "character"

Виконання коду class(5) показує нам, що 5є значенням числового типу даних numeric, а class("5") відповідає тексту character, тому арифметична операція додавання між цими значеннями неможлива.

2.2.2 Перевірка та привдення типів даних

У випадку коли тип даних потрібно визначити у процесі виконання програми/коду та перетворити значення використовується приведння типів даних.

Приведення типів даних - операція перетворення значення з одного типу даних в інший. Важливо памятати, що не завжди приведення типів даних може бути здійснено. Так, наприклад, значення "5" (character) можна досить просто привести до 5 (numeric), проте "five" не буде зрозумілим для інтерпритатора.

Для перевірки належності елемента до певного типу даних використовують спеціальну функцію is.назва_типу(значення). Ця функція повертає TRUE, якщо елемент належить даному типу і FALSE, якщо не належить.

Розглянемо приклад:

my_numeric <- 5
my_character <- "five"
my_logical <- FALSE

is.numeric(my_numeric)
## [1] TRUE
is.character(my_numeric)
## [1] FALSE

Для перетворення типу даних можна скористатися функцією as.назва_типу(значення). У результаті виконання функції буде повернуто значення потрібного типу або пусте значення NA, якщо таке приведення не є можливим:

a <- 5
b <- "10"
c <- "10, 20"
as.numeric(b)
## [1] 10
as.numeric(c)
## Warning: NAs introduced by coercion
## [1] NA

Результат виконання функцій можна записувати у змінні і використовувати у наступних обчисленнях:

a <- 5
b <- "10"
b <- as.numeric(b)
a + b
## [1] 15
number <- as.integer(54)
typeof(number)
## [1] "integer"
class(number)
## [1] "integer"

Повний перелік типів та методів перевірки і приведення їх типів ображений нижче:

Назва типу Метод перевірки типу Метод приведення типу
Array is.array as.array
Character is.character as.character
Complex is.complex as.complex
Dataframe is.data.frame as.data.frame
Double is.double as.double
Factor is.factor as.factor
List is.list as.list
Logical is.logical as.logical
Matrix is.matrix as.matrix
Numeric is.numeric as.numeric
Raw is.raw as.raw
Time series (ts) is.ts as.ts
Vector is.vector as.vector

2.3 Оператори

2.3.1 Арифметичні оператори

R можна використовувати як звичайни калькулятор.

Розглянемо набір звичних арифметичних операторів, що відомі з початкової школи: * Додавання: +. * Віднімання: -. * Ділення: /. * Множення: *.

А також більш складні оператори: * Піднесення до степеня: ^ (вводиться з клавіатури як Shift+6 на ENG-розкладці клавіатури). * Остача від ділення (ще може називатися “ділення по модулю”): %% (вводиться з клавіатури як Shift+5). * Ділення націло: %/%.

Розглянемо приклад додавання чисел:

5 + 10
## [1] 15
5 + 4 + 15
## [1] 24
5 + 53 + 343
## [1] 401
(5 + 8) + (4 + 9)
## [1] 26
Примітка. Використання “круглих” дужок у прогрмуванні виразах має пріоритет аналогічний до загальноприйнятих у математиці.

Розглянемо приклад віднімання чисел:

47 - 21
## [1] 26
15 - (10 - 25)
## [1] 30

Примітка. Заміна знаків до/в “дужках” тут працює так само як працювала у школі :)

Приклади множення чисел:

5 * 3
## [1] 15
5 * (2 + 5)
## [1] 35

Приклади ділення чисел:

12 / 2
## [1] 6
(4 + 7) / 3
## [1] 3.666667

Піднесення до степеня за допомогю оператора ^ є досить простим. Так, наприклад, 3^2 дорівнює 9, а 2^3 - це 2*2*2 і дорівнює 8.

5^2
## [1] 25
(1+3)^3 + 100 
## [1] 164

Остача від ділення дозволяє знайти залишок одного числа від ділення на інше число.

Наприклад, остача від ділення націло 5 на 2 дорівнює 1, бо 2 * 2 (=4) + 1 = 5

28 %% 7
## [1] 0
17%%5
## [1] 2

Ділння націло залишає лише цілу частину від ідленнядвох чисел:

28 %/% 7
## [1] 4
17 %/% 5 
## [1] 3
Sys.setlocale("LC_CTYPE", "ukrainian")
## [1] "Ukrainian_Ukraine.1251"
# пробіли між цифрами та операторами можна не лишати, це робиться для зручності візуального сприйняття коду

В окремих випадках інтерпритатори R можуть некоректно читати або взагалі ввжати за помилку наявність кирилиці у коді. Тоді варто вказати явно локалізацію, яку Ви бажаєте використовувати. Для української локалізації варто на початку коду додати рядок:

Sys.setlocale("LC_CTYPE", "ukrainian")

2.3.2 Оператори відношення

Оператори відношення відповідають за порівнняння двох об’єктів між собою та повертають значення логічного типу TRUE, якщо результат істинний та FALSE, якщо результат хибний.

Перелік операторів відношення:

  • Більше або дорівнює >=.
  • Менше <.
  • Менше або дорівнює <=.
  • Дорівнює ==.
  • Не дорівнює !=

Для демонстрації принципів роботи операторів відношення оголосимо 3 змінні a, b та c.

a <- 12
b <- 5
c <- 7

Розгялнемо кілька прикладів використання описаних вище операторів.

Оператори, що відповідають за первірку на “більше/менше”:

a > b
## [1] TRUE
b + c < a
## [1] FALSE
b + c <= a
## [1] TRUE

Оператори, що відповідають за перевірку на “рівність/нерівність”:

a != b
## [1] TRUE
a == b + c
## [1] TRUE
b == c
## [1] FALSE

2.3.3 Логічні оператори

До логічних операторів у R відносяться:

  • І & (амперсант, Shift-7) - виконання усіх умов одночасно.
  • АБО | (вертикальна риска, Shift+\) - виконання однієї із умов.
  • НЕ ! (знак оклику, Shift+1) - заперечення.

Важливо розуміти відмінності між цими операторами вміти використовувати результи їх роботи. Для початку варто розглянути таблицю істинності:

A B Оператор І Оператор АБО Заперечення A (не A)
FALSE FALSE FALSE FALSE TRUE
FALSE TRUE FALSE TRUE TRUE
TRUE FALSE FALSE TRUE FALSE
TRUE TRUE TRUE TRUE FALSE

Матеріали розділу не доповнені прикладами.


2.4 Корисні математичні функції

2.4.1 Заокруглення чисел (round, ceiling, floor, trunc, signif)

Як ми знаємо з математики, що заокруглення чисел буває “вверх”, “вниз” або відносно деякого значення, зазвичай пов’язаного із цифрою 5 (3.6 заокруглюємо до цілого як 4, а 3.2 як 3, ввжаючи 3.5 межею).

Увага! Заокрулення чисел у програмуванні може призводити до помилок у результатах обчислень. Для задач бізнесу або технічних процесів мінімальні відхилення можуть призводити до викривлених результатів або збоїв у системах.

Функція round()

  Примітка. Тут і надалі функції будуть позначатися як назва() (назва і “круглі” дужки).

Для заокруглення дійних чисел (з дробовою частиною) за правилом <0.5 & >=0.5 (не знаю як називається науково) використовується функція round(x, y), де x - число, y - точність (кількість знаків після коми/крапки). Наприклад:

round(3.557, 2)
## [1] 3.56
round(3.241, 2)
## [1] 3.24
round(-3.557, 2)
## [1] -3.56
round(-3.241, 2)
## [1] -3.24

Також можна використати round(x) з одним параметром, тоді заокруглення відбудеться до цілої частини, наприклад:

round(124.345)
## [1] 124

Функція floor()

Для заокруглення до найближчого меншого цілого числа слід скористатися функцією floor():

floor(3.557)
## [1] 3
floor(3.241)
## [1] 3
floor(-3.557)
## [1] -4
floor(-3.241)
## [1] -4

Функція ceiling()

Для заокруглення до найближчого більшого цілого числа слід скористатися функцією ceiling():

ceiling(3.557)
## [1] 4
ceiling(3.241)
## [1] 4
ceiling(-3.557)
## [1] -3
ceiling(-3.241)
## [1] -3

Функція trunc()

Функція trunc() у R використовується для отримання найбільшого цілого числа, яке більше або рівне x. Простими словами це означає, що для чисел менших 0 (x < 0) trunc() працює як celing(), а для чисел більших нуля x > 0, як floor():

x <- 5.34
print(paste("trunc:", trunc(x), "celing:", ceiling(x), "floor:", floor(x), sep = " "))
## [1] "trunc: 5 celing: 6 floor: 5"
x <- x * -1
print(paste("trunc:", trunc(x), "celing:", ceiling(x), "floor:", floor(x), sep = " "))
## [1] "trunc: -5 celing: -5 floor: -6"

Функція signif()

Інколи виникає потреба заокруглити не десяткову частину числа, а десятки, сотні, тисячі і так далі. Розглядемо варіант, коли у нас є велике число 11 547 741.3 і нам потрібно коротко його записати як 11.5 млн Для таких задач можна використати функцію signif(x,y), де x - число, яке потрібно заокруглити до певного порядку, y - порядок заокруглення (рахувати від початку). Наприклад:

big_number <- 11547741.3
rounded_big_number <- signif(big_number,3)
rounded_big_number
## [1] 11500000
rounded_big_number / 1000000
## [1] 11.5

2.4.2 Послідовності чисел (seq, rep)

Матеріали розділу у процесі підготовки.

2.4.3 Генерація псевдовипадкових чисел

Матеріали розділу у процесі підготовки.

runif(10)
##  [1] 0.990787443 0.529903455 0.913060406 0.468849184 0.400815174 0.221541355
##  [7] 0.406517213 0.340054824 0.273642196 0.003018643
sample(100)
##   [1]  81  75  34  67  58  56  32   7  80  18  60  46  37  20  68  91  39  87
##  [19]  36  23   6  93  24  94 100  73  40  96  50  10  82  62  92  31   5  35
##  [37]  79  28   1  74   4  99  59   9  14  53  44  89  19  71  27  97  41   8
##  [55]  22  26  78  88  16  12  13  64   3  63  43  48  49  90  83  72  51  17
##  [73]  30  66  69  77  15  57  85  61  76  11  42  95  70  54  33  25  98  86
##  [91]  84  38  47   2  65  55  29  21  45  52

2.4.4 Інші математичні функції та константи R

Окрім описаного вище набору функцій R містить дуже велику кількість реалізованих функцій з різних сфер науки, бізнесу, техніки тощо. Прочитати про них можна з офіційної документації пакетів, у яких вони реалізовані та знайти за допомогою функції help() або ?name.

Далі розглянемо перелік найпоширеніших функцій, що використовуються для розв’язання навчальних задач під час вивчення основ програмування.

Функція Призначення, опис
log(x) Логарифм числа x за основою e
log(x,n) Логарифм числа x за основою n
exp(x) e у степені x
sqrt(x) Корінь квадратний числа x
factorial(x) Факторіал числа x
abs(x) Модуль числа x

Також у R доступні ряд тригонометричних функцій, які вивчалися у школі і не тільки, серед них cos(x), sin(x), tan(x), а також acos(x), asin(x), atan(x), acosh(x), asinh(x), atanh(x).

Детальніше про кожну з них можна почитати у документації за допомогою кодманди help(function).

2.5 Введення-виведння даних

Матеріали розділу у процесі підготовки.