Wykresy słupkowe porównują kategorie
Wykres słupkowy odpowiada na pytanie "ile czego?": jeden słupek na kategorię, a długość słupka pokazuje jej wartość. W bazowym R służy do tego funkcja barplot(), a jej wejściem jest po prostu wektor wysokości. Jeśli nadasz wektorowi nazwy, staną się one podpisami pod słupkami:
visits <- c(Mon = 42, Tue = 51, Wed = 47, Thu = 60, Fri = 78)
barplot(visits,
main = "Store visits by day",
ylab = "Visits")
Pięć szarych słupków podpisanych dniami, rosnących od skromnego poniedziałku do piątkowego szczytu prawie dwa razy wyższego. Nic do instalowania, nic do konfigurowania: jeśli umiesz zbudować nazwany wektor, umiesz go narysować.
Edytory na tej stronie pokazują tylko wynik tekstowy, więc wywołania barplot() to statyczne fragmenty do wklejenia w lokalnej sesji R. Krok zliczania przed nimi działa jednak bez problemu, a to on jest najważniejszy.
Prawdziwy schemat pracy: najpierw table(), potem barplot()
W praktyce rzadko masz gotowe, zliczone wysokości. Masz surową kolumnę etykiet kategorii (jeden wiersz na odpowiedź w ankiecie, zamówienie, użytkownika), a prawdziwa praca to zliczanie. table() robi to jednym wywołaniem, a jej wynik to nazwany wektor liczebności, czyli dokładnie to, czego chce barplot():
Wykres to już tylko jedna linijka więcej:
barplot(sort(t, decreasing = TRUE),
main = "Survey responses",
ylab = "Count")
Te dwa kroki, table() i potem barplot(), to najczęstszy sposób tworzenia wykresu słupkowego w R. Posortowanie tabeli to tanie ulepszenie: słupki ułożone według wysokości czyta się szybciej niż alfabetycznie, chyba że kategorie mają naturalny porządek (dni, miesiące, poziomy dawki). Wtedy czynnik z poprawnie uporządkowanymi poziomami sprawi, że table() nie ułoży ich alfabetycznie. Dla słupków wymagających prawdziwej agregacji (sumy lub średnie w grupach zamiast liczby wierszy) najpierw wykonaj krok group-by-summarize i przekaż wynik do barplot().
Etykiety i styl
Etykiety zwykle pochodzą z nazw wektora, ale names.arg je nadpisuje, co przydaje się, gdy kody w danych nie nadają się dla odbiorców:
barplot(visits,
names.arg = c("Monday", "Tuesday", "Wednesday",
"Thursday", "Friday"),
col = "steelblue",
border = NA,
main = "Store visits by day",
las = 2)
colwypełnia słupki kolorem; przekaż wektor, żeby pokolorować każdy słupek osobno, ale nie używaj tęczy bez powodu. Kolor powinien coś znaczyć, np. wyróżniać ten jeden słupek, o którym mówisz.border = NAusuwa obrys słupków, co daje czystszy wygląd.las = 2obraca etykiety osi prostopadle do niej, co rozwiązuje problem nachodzących na siebie długich nazw kategorii. Przy naprawdę długich nazwach połącz to z większym dolnym marginesem (par(mar = c(8, 4, 4, 2))).
Słupki grupowane i skumulowane z macierzy
Aby pokazać naraz dwa wymiary kategorii, np. sprzedaż według kanału i kwartału, przekaż do barplot() macierz. Każda kolumna staje się jedną pozycją na osi kategorii, a wiersze stają się słupkami składowymi:
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 stawia oba kanały ramię w ramię w każdym kwartale, co najlepiej sprawdza się przy bezpośrednim porównywaniu kanałów. Domyślny wariant skumulowany podkreśla sumę w każdym kwartale, a podział widać wewnątrz słupka. Uczciwie pokazuje sumy, ale utrudnia porównywanie wewnętrznych segmentów między słupkami, bo ich podstawy się przesuwają. legend.text = rownames(sales) dodaje legendę, dzięki której obie wersje są czytelne.
Jeszcze jeden przełącznik: horiz = TRUE układa słupki wzdłuż osi poziomej. To najwygodniejszy układ przy wielu kategoriach o długich nazwach: każda etykieta stoi w osobnym wierszu obok swojego słupka i nie trzeba jej obracać.
Wykres słupkowy czy histogram?
Te dwa wykresy są bez przerwy mylone, a różnicę warto poznać w pół minuty. Wykres słupkowy porównuje odrębne kategorie: oś to zbiór etykiet, słupki są rozdzielone, a zmiana ich kolejności jest dozwolona. Histogram dzieli na przedziały jedną zmienną liczbową: oś to ciągła skala, słupki się stykają, bo przedziały następują po sobie, a zmiana ich kolejności nie miałaby sensu. Jeśli kolumna zawiera słowa ("Yes", "Chrome", "Q3"), potrzebujesz barplot(table(x)). Jeśli zawiera pomiary (wzrost, ceny, czasy odpowiedzi), potrzebujesz histogramu i hist(x).
ggplot2: geom_col a geom_bar
Wersja w ggplot2 ma dwa geomy, a wybór zależy od tego, czy zliczanie jest już zrobione:
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() to table() wbudowane w wykres: przyjmuje jeden wiersz na obserwację i zlicza. geom_col() przyjmuje zagregowane dane i mapuje kolumnę y na wysokość słupka, co odpowiada klasycznemu barplot(). Podanie już zliczonych danych do geom_bar() to typowa pułapka początkujących: zlicza on wiersze (po jednym), więc każdy słupek ma tę samą wysokość.
Co warto zapamiętać
barplot(heights)rysuje nazwany wektor, atable(x)tworzy dokładnie taki kształt z surowych danych kategorycznych, więcbarplot(table(x))to podstawowy idiom.- Posortuj tabelę (albo ustaw poziomy czynnika) przed rysowaniem; kolejność słupków jest częścią przekazu.
- Macierz daje słupki grupowane (
beside = TRUE) lub skumulowane (domyślnie); dodajlegend.text = rownames(m). names.arg,col,las = 2ihoriz = TRUEobsługują podpisy; słupki poziome są najlepsze przy długich nazwach.- Kategorie → wykres słupkowy; przedziały liczbowe → histogram. W ggplot2: surowe wiersze →
geom_bar(), obliczone wysokości →geom_col().
Dalej: samo ggplot2, czyli gramatyka, która buduje wszystkie te wykresy i wiele innych z tych samych kilku łączonych elementów.
Najczęściej zadawane pytania
Jak zrobić wykres słupkowy w R?
Wywołaj barplot() na wektorze wysokości. Nadaj wektorowi nazwy albo zbuduj go przez table(), którego wynik jest już nazwany, a każdy element stanie się jednym podpisanym słupkiem: barplot(table(df$category)).
Jak zrobić grupowany lub skumulowany wykres słupkowy w R?
Przekaż macierz. Każda kolumna staje się jedną pozycją na osi kategorii; beside = TRUE rysuje wiersze jako słupki stojące obok siebie (grupowane), a domyślne beside = FALSE układa je jeden na drugim. Dodaj legend.text = rownames(m), żeby czytelnik odróżnił wiersze.
Czym różni się barplot() od hist() w R?
barplot() porównuje odrębne kategorie: jeden słupek na kategorię, słupki rozdzielone. hist() dzieli jedną zmienną liczbową na kolejne przedziały, a słupki się stykają, bo oś to ciągła skala. Jeśli zmienna zawiera słowa, potrzebujesz barplot(table(x)); jeśli liczby, potrzebujesz hist(x).
Używać geom_bar czy geom_col w ggplot2?
geom_bar() liczy za ciebie: podajesz surowe obserwacje, a on zlicza każdą kategorię. geom_col() rysuje wartości już obliczone: jeden wiersz na słupek i kolumna z wysokością. Przekazanie już zliczonych danych do geom_bar() to klasyczny błąd; w takim przypadku potrzebne jest geom_col().