Menu

Столбчатая диаграмма в R: barplot() по количествам и таблицам

Как построить столбчатую диаграмму в R через barplot() — из именованного вектора или table(), сгруппированные и накопленные столбцы из матрицы, оформление и geom_col против geom_bar.

На этой странице есть исполняемые редакторы: меняйте, запускайте и сразу видите результат.

Столбчатые диаграммы сравнивают категории

Столбчатая диаграмма отвечает на вопрос «сколько каждого?» — по столбцу на категорию, где длина столбца показывает значение категории. В R базовая функция называется barplot(), и на вход ей идёт просто вектор высот. Дайте вектору имена — и имена станут подписями под столбцами:

visits <- c(Mon = 42, Tue = 51, Wed = 47, Thu = 60, Fri = 78)

barplot(visits,
        main = "Store visits by day",
        ylab = "Visits")

Пять серых столбцов, подписанных днями, поднимаются от скромного понедельника к пятничному пику почти вдвое выше. Ничего устанавливать, ничего настраивать: если вы умеете построить именованный вектор, вы умеете его нарисовать.

Запускаемые редакторы на этой странице показывают только текстовый вывод, поэтому вызовы barplot() здесь являются статичными сниппетами для вставки в локальную сессию R, — но шаг подсчёта перед ними выполняется прекрасно, и именно он важнее всего.

Настоящий рабочий процесс: сначала table(), потом barplot()

На практике у вас редко есть аккуратно подсчитанные высоты. У вас есть сырой столбец меток категорий — по строке на ответ анкеты, на заказ, на пользователя, — и подсчёт является настоящей работой. table() делает это одним вызовом, и её вывод — именованный вектор количеств, то есть ровно то, что нужно barplot():

А дальше график — ещё одна строка:

barplot(sort(t, decreasing = TRUE),
        main = "Survey responses",
        ylab = "Count")

Эти два шага — table(), затем barplot() — самый частый сценарий построения столбчатых диаграмм в R. Предварительная сортировка таблицы — дешёвое улучшение: столбцы, упорядоченные по высоте, читаются быстрее, чем упорядоченные по алфавиту, — если только у категорий нет естественного порядка (дни, месяцы, уровни дозы), и в этом случае фактор с правильно упорядоченными уровнями не даст table() расставить их по алфавиту. Для столбцов, требующих настоящей агрегации — сумм или средних по группам, а не количества строк, — сначала выполните шаг группировки и сводки и передайте результат в barplot().

Подписи и оформление

Подписи обычно берутся из имён вектора, но names.arg их переопределяет — полезно, когда коды из данных не годятся для аудитории:

barplot(visits,
        names.arg = c("Monday", "Tuesday", "Wednesday",
                      "Thursday", "Friday"),
        col    = "steelblue",
        border = NA,
        main   = "Store visits by day",
        las    = 2)
  • col заливает столбцы; передайте вектор, чтобы раскрасить каждый по-своему, но не поддавайтесь радуге по умолчанию — цвет должен что-то означать, например выделять тот единственный столбец, о котором вы говорите.
  • border = NA убирает контуры столбцов ради более чистого вида.
  • las = 2 поворачивает подписи оси перпендикулярно ей — решение для длинных названий категорий, налезающих друг на друга. Сочетайте это с бо́льшим нижним полем (par(mar = c(8, 4, 4, 2))), если названия действительно длинные.

Сгруппированные и накопленные столбцы из матрицы

Чтобы показать сразу два категориальных измерения — скажем, продажи по каналу и кварталу, — передайте barplot() матрицу. Каждый столбец матрицы становится одной позицией на оси категорий, а строки становятся подстолбцами:

sales <- matrix(c(12, 18,   15, 22,   20, 19,   24, 27),
                nrow = 2,
                dimnames = list(c("Online", "Retail"),
                                c("Q1", "Q2", "Q3", "Q4")))

# Grouped: rows stand next to each other within each quarter
barplot(sales, beside = TRUE,
        col = c("steelblue", "orange"),
        legend.text = rownames(sales),
        main = "Sales by channel and quarter")

# Stacked: rows pile up into one total bar per quarter (the default)
barplot(sales, beside = FALSE,
        col = c("steelblue", "orange"),
        legend.text = rownames(sales))

beside = TRUE ставит два канала плечом к плечу внутри каждого квартала — лучший вариант, когда нужно сравнивать каналы напрямую. Накопленный вариант по умолчанию подчёркивает итог за квартал, показывая разбивку внутри каждого столбца; он честен для итогов, но затрудняет сравнение внутренних сегментов между столбцами, поскольку их основания смещаются. legend.text = rownames(sales) добавляет легенду, которая делает читаемым любой из вариантов.

Ещё один переключатель: horiz = TRUE укладывает столбцы вдоль горизонтальной оси. Это самая гуманная раскладка для множества категорий с длинными названиями — каждая подпись сидит на своей строке рядом со своим столбцом, поворачивать ничего не нужно.

Столбчатая диаграмма или гистограмма?

Их постоянно путают, и различие стоит тридцати секунд: столбчатая диаграмма сравнивает различные категории — ось это набор меток, столбцы разделены, и переупорядочивать их допустимо. Гистограмма разбивает на интервалы одну числовую переменную — ось непрерывна, столбцы соприкасаются, потому что интервалы последовательны, и переупорядочивать их было бы бессмыслицей. Если в вашем столбце слова («Yes», «Chrome», «Q3»), вам нужен barplot(table(x)). Если там измерения (рост, цены, время отклика), вам нужна гистограмма и hist(x).

ggplot2: geom_col против geom_bar

Версия на ggplot2 приходит в двух геомах, различающихся тем, выполнен ли подсчёт заранее:

library(ggplot2)

# geom_bar(): raw observations in, counting done for you
ggplot(survey, aes(x = response)) +
    geom_bar(fill = "steelblue")

# geom_col(): heights already computed, one row per bar
totals <- data.frame(day = c("Mon", "Tue", "Wed", "Thu", "Fri"),
                     visits = c(42, 51, 47, 60, 78))

ggplot(totals, aes(x = day, y = visits)) +
    geom_col(fill = "steelblue")

geom_bar() — это table(), встроенная в график: он берёт по строке на наблюдение и подсчитывает. geom_col() берёт предварительно агрегированные данные и отображает столбец y на высоту столбика — эквивалент классического barplot(). Передача уже подсчитанных данных в geom_bar() — стандартная ловушка новичка: он считает строки (по одной на каждую), и все столбцы выходят одинаковой высоты.

Что вы уносите с собой

  • barplot(heights) рисует именованный вектор, а table(x) производит ровно такую форму из сырых категориальных данных, поэтому barplot(table(x)) — ключевая идиома.
  • Сортируйте таблицу (или задавайте уровни фактора) перед построением; порядок столбцов — часть сообщения.
  • Матрица даёт сгруппированные (beside = TRUE) или накопленные (по умолчанию) столбцы; добавляйте legend.text = rownames(m).
  • names.arg, col, las = 2 и horiz = TRUE отвечают за подписи; горизонтальные столбцы лучше всего подходят для длинных названий.
  • Категории → столбчатая диаграмма; числовые интервалы → гистограмма. В ggplot2: сырые строки → geom_bar(), вычисленные высоты → geom_col().

Дальше: сам ggplot2 — грамматика, которая строит все эти графики и множество других из одних и тех же немногих составных частей.

Часто задаваемые вопросы

Как построить столбчатую диаграмму в R?

Вызовите barplot() на векторе высот. Дайте вектору имена — или постройте его через table(), чей вывод уже именованный, — и каждый элемент станет одним подписанным столбцом: barplot(table(df$category)).

Как сделать сгруппированную или накопленную столбчатую диаграмму в R?

Передайте матрицу. Каждый столбец матрицы становится одной позицией на оси категорий; beside = TRUE рисует строки как столбцы, стоящие рядом (сгруппированные), тогда как умолчание beside = FALSE их накапливает. Добавьте legend.text = rownames(m), чтобы читатели могли различать строки.

В чём разница между barplot() и hist() в R?

barplot() сравнивает различные категории — по столбцу на категорию, столбцы разделены. hist() разбивает одну числовую переменную на последовательные интервалы — столбцы соприкасаются, потому что ось непрерывна. Если ваша переменная состоит из слов, вам нужен barplot(table(x)); если из чисел — hist(x).

Что использовать в ggplot2: geom_bar или geom_col?

geom_bar() считает за вас: дайте ему сырые наблюдения — и он подсчитает каждую категорию. geom_col() рисует уже вычисленные значения: дайте ему по строке на столбец плюс столбец высоты. Передача предварительно подсчитанных данных в geom_bar() — классическая ошибка; там нужен geom_col().

Coddy programming languages illustration

Учитесь программировать с Coddy

НАЧАТЬ