LEARN X · ЗА 15 МИН
R
R за 15 минут: векторы, data frames, apply-семейство, факторы, матрицы, функции, статистика и графика — весь язык одной страницей в комментариях кода.
R — язык и среда для статистических вычислений и анализа данных. Всё ниже — рабочий код с результатами в комментариях. Запускайте построчно в консоли R или RStudio.
1. Вывод и комментарии
# Однострочный комментарий начинается с #
# Многострочных комментариев в R нет — каждая строка со своим #
print("Привет, R") # [1] "Привет, R" (print добавляет кавычки и индекс [1])
cat("Привет", "R", "\n") # Привет R (cat склеивает через пробел, без кавычек и [1])
cat("Сумма:", 2 + 2, "\n") # Сумма: 4
42 # [1] 42 (в консоли значение печатается автоматически)
"строка" # [1] "строка"
2. Переменные и присваивание
Канонический оператор присваивания в R — <- (стрелка влево). Знак = тоже работает, но <- считается идиоматичным.
x <- 10 # основное присваивание (стрелка)
y = 5 # тоже работает, но используется реже
15 -> z # можно и вправо: z станет 15
x # [1] 10
# Базовые типы
n <- 3.14 # numeric (число с плавающей точкой)
i <- 7L # integer (суффикс L делает целое)
s <- "текст" # character (строка)
b <- TRUE # logical (TRUE/FALSE, можно T/F)
class(n) # [1] "numeric"
class(i) # [1] "integer"
class(s) # [1] "character"
class(b) # [1] "logical"
is.numeric(n) # [1] TRUE
as.character(42) # [1] "42" (приведение типов: as.*)
NA # пропущенное значение (Not Available)
NULL # отсутствие объекта
Inf # бесконечность (1/0)
NaN # не число (0/0)
3. Векторы
Вектор — базовая структура R. Почти всё в R векторизовано: операции применяются к каждому элементу.
v <- c(1, 2, 3, 4, 5) # c() = combine, создаёт вектор
v # [1] 1 2 3 4 5
v * 2 # [1] 2 4 6 8 10 (операция к каждому элементу)
v + c(10, 20, 30, 40, 50) # [1] 11 22 33 44 55 (поэлементно)
sqrt(v) # [1] 1.000 1.414 1.732 2.000 2.236
# Индексация — с ЕДИНИЦЫ (не с нуля!)
v[1] # [1] 1 (первый элемент)
v[c(1, 3)] # [1] 1 3 (несколько элементов)
v[-1] # [1] 2 3 4 5 (минус = исключить элемент)
v[v > 3] # [1] 4 5 (логическая индексация — фильтр)
length(v) # [1] 5
# Генерация последовательностей
1:5 # [1] 1 2 3 4 5 (диапазон)
seq(0, 10, by = 2) # [1] 0 2 4 6 8 10
seq(0, 1, length.out = 5) # [1] 0.00 0.25 0.50 0.75 1.00
rep(c(1, 2), times = 3) # [1] 1 2 1 2 1 2
rep(c(1, 2), each = 3) # [1] 1 1 1 2 2 2
# Именованные элементы
w <- c(a = 1, b = 2, c = 3)
w["b"] # b\n# 2
4. Операторы и условия
# Арифметика
7 %% 3 # [1] 1 (остаток от деления)
7 %/% 3 # [1] 2 (целочисленное деление)
2 ^ 3 # [1] 8 (возведение в степень, можно 2**3)
# Сравнения возвращают logical
5 > 3 # [1] TRUE
5 == 5 # [1] TRUE
5 != 3 # [1] TRUE
# Логические операторы
TRUE & FALSE # [1] FALSE (& поэлементно для векторов)
TRUE | FALSE # [1] TRUE
!TRUE # [1] FALSE
# && и || — скалярные, для одиночных условий в if
# if / else
x <- 10
if (x > 5) {
cat("больше 5\n") # больше 5
} else if (x == 5) {
cat("равно 5\n")
} else {
cat("меньше 5\n")
}
# ifelse — ВЕКТОРИЗОВАННОЕ условие (работает над вектором)
nums <- c(-2, 5, -7, 3)
ifelse(nums > 0, "плюс", "минус") # [1] "минус" "плюс" "минус" "плюс"
5. Циклы и apply-семейство
В R циклы используют редко — предпочитают векторизацию и функции apply. Но они есть.
# Цикл for — по элементам вектора
for (i in 1:3) {
cat("шаг", i, "\n") # шаг 1 / шаг 2 / шаг 3
}
# while
n <- 3
while (n > 0) {
cat(n, "") # 3 2 1
n <- n - 1
}
# sapply — применяет функцию к каждому элементу, возвращает ВЕКТОР
sapply(1:4, function(x) x ^ 2) # [1] 1 4 9 16
# lapply — то же, но возвращает СПИСОК
lapply(1:2, function(x) x * 10) # [[1]] 10 [[2]] 20
# vapply — как sapply, но с проверкой типа результата (безопаснее)
vapply(1:3, function(x) x + 0.5, numeric(1)) # [1] 1.5 2.5 3.5
# apply — по строкам/столбцам матрицы (MARGIN: 1=строки, 2=столбцы)
m <- matrix(1:6, nrow = 2)
apply(m, 1, sum) # [1] 9 12 (сумма по строкам)
apply(m, 2, sum) # [1] 3 7 11 (сумма по столбцам)
6. Списки и факторы
# Список — может хранить элементы РАЗНЫХ типов
person <- list(name = "Аня", age = 30, langs = c("R", "Python"))
person$name # [1] "Аня" ($ — доступ по имени)
person[["age"]] # [1] 30 ([[ ]] — извлечь элемент)
person$langs[2] # [1] "Python"
str(person) # компактная структура объекта
names(person) # [1] "name" "age" "langs"
# Фактор — категориальная переменная (хранит уровни)
size <- factor(c("S", "L", "M", "S", "L"))
size # [1] S L M S L\n# Levels: L M S (уровни по алфавиту)
levels(size) # [1] "L" "M" "S"
table(size) # частоты: L=2 M=1 S=2
# Упорядоченный фактор (с порядком уровней)
size2 <- factor(c("S", "L", "M"), levels = c("S", "M", "L"), ordered = TRUE)
size2[1] < size2[2] # [1] TRUE (S < L по заданному порядку)
7. Матрицы
# Матрица — двумерный массив одного типа
m <- matrix(1:6, nrow = 2, ncol = 3)
m
# [,1] [,2] [,3]
# [1,] 1 3 5 (заполняется по столбцам по умолчанию)
# [2,] 2 4 6
matrix(1:6, nrow = 2, byrow = TRUE) # byrow=TRUE — заполнять по строкам
dim(m) # [1] 2 3 (строки, столбцы)
m[1, 2] # [1] 3 (элемент: строка 1, столбец 2)
m[1, ] # [1] 1 3 5 (вся первая строка)
m[, 2] # [1] 3 4 (весь второй столбец)
# Матричные операции
t(m) # транспонирование
m * 2 # [поэлементно] умножение на скаляр
a <- matrix(1:4, 2, 2)
a %*% a # %*% — матричное умножение (не поэлементное!)
rowSums(m) # [1] 9 12
colMeans(m) # [1] 1.5 3.5 5.5
8. Data Frames
Data frame — главная структура для табличных данных: столбцы могут быть разных типов, как таблица в БД или Excel.
df <- data.frame(
name = c("Аня", "Боря", "Вера"),
age = c(30, 25, 35),
city = c("Москва", "Казань", "Москва"),
stringsAsFactors = FALSE
)
df
# name age city
# 1 Аня 30 Москва
# 2 Боря 25 Казань
# 3 Вера 35 Москва
# Доступ к столбцам
df$age # [1] 30 25 35 ($ по имени)
df[["name"]] # [1] "Аня" "Боря" "Вера"
df[, "city"] # то же, что df$city
# Доступ к строкам/ячейкам: df[строка, столбец]
df[1, ] # вся первая строка
df[2, "age"] # [1] 25
# Фильтрация строк по условию
df[df$age > 28, ] # строки, где age > 28 (Аня и Вера)
df[df$city == "Москва", "name"] # [1] "Аня" "Вера"
# Новый столбец
df$adult <- df$age >= 18 # добавили логический столбец
nrow(df) # [1] 3 (число строк)
ncol(df) # [1] 4 (число столбцов)
head(df, 2) # первые 2 строки
names(df) # имена столбцов
9. Функции
# function() — определение функции. Последнее выражение = результат
square <- function(x) {
x ^ 2 # return не обязателен — возвращается последнее значение
}
square(4) # [1] 16
# Аргументы по умолчанию
greet <- function(name, greeting = "Привет") {
paste0(greeting, ", ", name, "!")
}
greet("Аня") # [1] "Привет, Аня!"
greet("Боря", "Здравствуй") # [1] "Здравствуй, Боря!"
greet(name = "Вера") # можно передавать по имени аргумента
# ... (многоточие) — произвольное число аргументов
sum_all <- function(...) {
sum(...) # передаём все аргументы дальше
}
sum_all(1, 2, 3, 4) # [1] 10
# Анонимная функция (lambda)
(function(x) x + 1)(5) # [1] 6
sapply(1:3, \(x) x * 2) # R 4.1+: \(x) — короткий синтаксис анонимки
10. Работа с данными и статистика
R создавался для статистики — встроенных функций для агрегации очень много.
x <- c(4, 8, 15, 16, 23, 42)
sum(x) # [1] 108
mean(x) # [1] 18
median(x) # [1] 15.5
min(x); max(x)# [1] 4 ; [1] 42
sd(x) # [1] 13.7... (стандартное отклонение)
range(x) # [1] 4 42
sort(x, decreasing = TRUE) # [1] 42 23 16 15 8 4
rev(x) # [1] 42 23 16 15 8 4 (разворот)
order(x) # индексы для сортировки
summary(x) # сводка: Min, 1st Qu, Median, Mean, 3rd Qu, Max
# table — частотная таблица
table(c("a", "b", "a", "c", "a")) # a=3 b=1 c=1
# Пропущенные значения NA
y <- c(1, 2, NA, 4)
mean(y) # [1] NA (NA «заражает» результат)
mean(y, na.rm = TRUE) # [1] 2.333 (na.rm — убрать NA перед расчётом)
is.na(y) # [1] FALSE FALSE TRUE FALSE
sum(is.na(y)) # [1] 1 (сколько пропусков)
11. Строки
paste("R", "это", "круто") # [1] "R это круто" (склейка через пробел)
paste0("abc", "def") # [1] "abcdef" (без разделителя)
paste(c("a", "b"), collapse = "-") # [1] "a-b" (склеить вектор)
# sprintf — форматирование (как в C)
sprintf("Возраст: %d, рост: %.2f м", 30, 1.755) # "Возраст: 30, рост: 1.75 м"
nchar("привет") # [1] 6 (длина строки)
toupper("абв") # [1] "АБВ"
tolower("АБВ") # [1] "абв"
substr("codechick", 1, 4) # [1] "code" (подстрока: с 1 по 4 символ)
strsplit("a,b,c", ",") # [[1]] "a" "b" "c" (разбить по разделителю)
trimws(" пробелы ") # [1] "пробелы" (убрать пробелы по краям)
# gsub / sub — замена по шаблону (gsub — все вхождения, sub — первое)
gsub("o", "0", "foobar") # [1] "f00bar"
sub("o", "0", "foobar") # [1] "f0obar"
grepl("bar", "foobar") # [1] TRUE (есть ли подстрока)
12. Графика и пакеты
В R графика встроена в язык, а экосистема пакетов (CRAN) огромна.
# Базовая графика (открывает окно с графиком)
plot(1:10, (1:10)^2) # точечный график y = x^2
plot(1:10, type = "l", col = "blue") # линия
hist(c(1, 2, 2, 3, 3, 3, 4)) # гистограмма
barplot(c(A = 3, B = 7, C = 5)) # столбчатая диаграмма
boxplot(c(1, 5, 3, 9, 2)) # ящик с усами
# Пакеты — расширения языка
install.packages("ggplot2") # установка с CRAN (один раз)
library(ggplot2) # подключить пакет в текущую сессию
require(dplyr) # как library, но возвращает FALSE без ошибки
# Популярные пакеты экосистемы:
# dplyr — манипуляции с data frame (filter, mutate, summarise)
# ggplot2 — декларативная «грамматика графики»
# tidyr — приведение данных в опрятный вид
# readr — быстрое чтение CSV/TSV
# Чтение и запись данных
# df <- read.csv("data.csv") # прочитать CSV в data frame
# write.csv(df, "out.csv", row.names = FALSE) # записать
?mean # справка по функции (откроет документацию)
help(plot) # то же самое