Menu

Histogram w R: hist() z przykładami

Jak zrobić histogram w R przez hist(): dobór przedziałów (breaks), wygląd słupków, skala gęstości, nałożenie krzywej normalnej i wersja w ggplot2.

Na tej stronie są działające edytory: edytuj, uruchamiaj i od razu zobacz wynik.

Co pokazuje histogram

Histogram odpowiada na jedno pytanie o jedną zmienną liczbową: jak rozkładają się wartości? Dzieli zakres danych na kolejne przedziały (ang. bins), liczy, ile obserwacji trafia do każdego, i rysuje dla każdego przedziału słupek o wysokości równej tej liczbie. Tam, gdzie danych jest dużo, słupki są wysokie, a tam, gdzie mało, niskie.

Ten jeden obrazek mówi rzeczy, których nie powie średnia ani odchylenie standardowe: czy dane mają jeden szczyt, czy dwa, czy są symetryczne, czy przesunięte w stronę jednego ogona, i czy są pojedyncze wartości daleko od reszty. Zwykle to pierwszy wykres, jaki robisz przy nowym zbiorze danych, zaraz obok liczb ze statystyki opisowej.

W R służy do tego funkcja hist() i wystarczy jedna linia.

Pierwszy histogram z hist()

Zasymulujmy wzrost 200 osób o rozkładzie normalnym wokół 170 cm z odchyleniem standardowym 10 (co robią set.seed() i rnorm(), wyjaśnia artykuł o liczbach losowych):

set.seed(42)
heights <- rnorm(200, mean = 170, sd = 10)

hist(heights)

R sam wybiera przedziały i rysuje dzwonowaty stos słupków: niskie słupki w okolicach 145 cm, rosnące przez sto sześćdziesiąt kilka, szczyt około 170 i symetryczny spadek za 190. Oś pionowa ma etykietę "Frequency" (surowe liczebności), a tytuł i etykieta osi pochodzą od nazwy zmiennej.

Ustawienia domyślne są celowo skromne. Działają tu wszystkie zwykłe argumenty upiększające:

hist(heights,
     main   = "Distribution of heights",
     xlab   = "Height (cm)",
     col    = "steelblue",
     border = "white")

col wypełnia słupki, border koloruje ich obrys, a border = "white" daje czysty wygląd rozdzielonych słupków, który widać w większości publikacji. Wszystko, co przewodnik po plot() mówi o kolorach i tytułach, obowiązuje bez zmian.

Szerokość przedziału: argument breaks

Najważniejszym argumentem hist() jest breaks, bo szerokość przedziału decyduje o tym, jaką historię opowiada wykres. Te same dane, dwa ustawienia:

hist(heights, breaks = 5)    # five wide bins: a crude, blocky bell
hist(heights, breaks = 30)   # thirty narrow bins: detail, plus noise

Przy breaks = 5 histogram jest tak zgrubny, że wszystko wygląda jak jeden gładki garb: drugie skupisko albo luka w danych byłyby niewidoczne. Przy breaks = 30 widać drobną strukturę, ale losowe drgania zaczynają udawać cechy danych. Żadne z ustawień nie jest "poprawne"; uczciwie jest wypróbować kilka i sprawdzić, które cechy przetrwają.

breaks przyjmuje trzy formy:

  • Liczba, np. breaks = 30: sugestia liczby przedziałów. R dopasowuje ją tak, żeby trafić w równe granice, więc możesz dostać 28 albo 33 przedziały. Każdego to kiedyś zaskakuje.
  • Wektor punktów podziału, np. breaks = seq(140, 200, by = 5): dokładne granice przedziałów, bez negocjacji. Używaj tego, gdy przedziały muszą się pokrywać w kilku porównywanych histogramach.
  • Nazwa reguły, np. breaks = "FD" dla reguły Freedmana-Diaconisa, która dobiera szerokość na podstawie rozrzutu danych i liczebności próby i dobrze radzi sobie z danymi skośnymi.

Histogram gęstości i krzywa normalna

Domyślnie wysokości słupków to liczebności (freq = TRUE). Ustawienie freq = FALSE przeskalowuje słupki tak, że ich łączne pole wynosi 1: to skala gęstości. Kształt się nie zmienia, zmienia się oś pionowa. Chodzi o to, że histogram gęstości jest w tej samej skali co funkcja gęstości prawdopodobieństwa, więc możesz nałożyć teoretyczną krzywą bezpośrednio na dane:

hist(heights,
     freq = FALSE,
     col = "gray90",
     main = "Heights vs. a normal curve",
     xlab = "Height (cm)")

curve(dnorm(x, mean = mean(heights), sd = sd(heights)),
      add = TRUE, col = "tomato", lwd = 2)

curve() z add = TRUE rysuje krzywą dzwonową na istniejącym histogramie (x w dnorm(x, ...) to symbol zastępczy, który wypełnia curve(), a nie twoja zmienna). Jeśli słupki przylegają do krzywej, model normalny jest rozsądny; tam, gdzie od niej odstają (ciężki ogon, drugi szczyt), modelowi czegoś brakuje. Pomiń freq = FALSE, a krzywa będzie bezużytecznie pełzać po dole wykresu, bo liczebności i gęstości są w różnych skalach.

Liczby stojące za słupkami

hist() nie tylko rysuje: zwraca też podział na przedziały jako listę. Z plot = FALSE całkiem pomija rysowanie i tylko liczy, więc ten przykład możesz uruchomić od razu tutaj:

h$counts to histogram w postaci danych: każda liczba to wysokość jednego słupka. Linia z table(cut(...)) to tekstowy odpowiednik: cut() dzieli wartości na przedziały, table() liczy każdy przedział. To dobry test poprawności, który warto wypisać przed wykresem albo zamiast niego. Jeśli przypiszesz wynik bez plot = FALSE (h <- hist(heights)), R narysuje wykres i zwróci listę; przypisanie nie wyłącza rysowania.

Histogramy w ggplot2

Wersja w ggplot2 zamienia breaks na binwidth, co często jest bardziej naturalnym pokrętłem: podajesz, jak szeroki jest przedział w jednostkach danych, zamiast ile przedziałów chcesz:

library(ggplot2)

ggplot(data.frame(heights), aes(x = heights)) +
    geom_histogram(binwidth = 5, fill = "steelblue", color = "white") +
    labs(title = "Distribution of heights", x = "Height (cm)", y = "Count")

binwidth = 5 oznacza, że każdy słupek obejmuje 5 cm. ggplot2 ostrzega, jeśli nie ustawisz binwidth, i po cichu przyjmuje 30 przedziałów. Posłuchaj ostrzeżenia, bo domyślna wartość rzadko jest właściwą szerokością dla twoich danych. Do szybkiego podglądu jednej zmiennej hist() wymaga mniej pisania; ggplot2 opłaca się, gdy histogram potrzebuje paneli, grup albo spójnego motywu z resztą twoich wykresów.

Co warto zapamiętać

  • Histogram pokazuje rozkład jednej zmiennej liczbowej: hist(x) i gotowe.
  • breaks to argument, który ma znaczenie: liczba jest tylko sugestią, wektor ustala dokładne granice, a "FD" wybiera rozsądną szerokość. Zawsze wypróbuj więcej niż jedno ustawienie.
  • freq = FALSE przełącza na skalę gęstości i właśnie dzięki temu curve(dnorm(...), add = TRUE) sensownie nakłada krzywą normalną.
  • hist(x, plot = FALSE) zwraca przedziały jako dane ($breaks, $counts, $mids); table(cut(x, breaks)) to odpowiednik czysto tekstowy.
  • W ggplot2 użyj geom_histogram(binwidth = ...) i ustaw binwidth samodzielnie.

Dalej: wykres pudełkowy, czyli wykres rozkładu, który najlepiej sprawdza się przy porównywaniu grup obok siebie.

Najczęściej zadawane pytania

Jak zrobić histogram w R?

Wywołaj hist(x) na wektorze liczbowym. R dzieli zakres x na przedziały i rysuje jeden słupek na przedział, a wysokość słupka pokazuje, ile wartości do niego trafia. Dodaj breaks =, żeby sterować liczbą przedziałów, i col =, żeby pokolorować słupki.

Co robi argument breaks w hist()?

Steruje podziałem na przedziały. Pojedyncza liczba, np. breaks = 30, to sugestia, ilu przedziałów użyć (R zaokrągla do równych granic), wektor, np. breaks = seq(140, 200, by = 5), ustala dokładne punkty podziału, a breaks = "FD" stosuje regułę Freedmana-Diaconisa.

Jak nałożyć krzywą normalną na histogram w R?

Narysuj histogram w skali gęstości przez freq = FALSE, a potem dodaj krzywą: curve(dnorm(x, mean = mean(data), sd = sd(data)), add = TRUE). W skali częstości krzywa leżałaby bezużytecznie tuż przy zerze, dlatego freq = FALSE jest niezbędne.

Czym różni się histogram od wykresu słupkowego?

Histogram dzieli na przedziały jedną zmienną liczbową, więc oś pozioma jest skalą ciągłą, a słupki się stykają. Wykres słupkowy porównuje odrębne kategorie, więc słupki są rozdzielone. W R to hist() dla liczb i barplot() dla liczebności kategorii.

Ilustracja języków programowania w Coddy

Ucz się programowania z Coddy

ZACZNIJ