Menu

R의 히스토그램: 예제로 배우는 hist()

R에서 hist()로 히스토그램 만드는 방법 - 구간(breaks) 고르기, 막대 꾸미기, 밀도 척도로 전환하기, 정규 곡선 겹쳐 그리기, 그리고 ggplot2 버전.

이 페이지에는 실행 가능한 에디터가 있습니다 - 편집하고 실행하면 결과를 바로 볼 수 있습니다.

히스토그램이 보여 주는 것

히스토그램은 하나의 수치형 변수에 대한 한 가지 질문에 답합니다: 값들이 어떻게 분포하는가? 데이터의 범위를 연속된 구간(bin)으로 자르고, 각 구간에 몇 개의 관측값이 들어가는지 세어, 그 개수를 높이로 하는 막대를 구간마다 그립니다. 데이터가 밀집한 곳의 막대는 높고, 희박한 곳의 막대는 낮습니다.

이 그림 하나가 평균과 표준편차로는 알 수 없는 것을 알려 줍니다: 봉우리가 하나인지 둘인지, 대칭인지 한쪽 꼬리로 치우쳐 있는지, 나머지에서 멀리 떨어진 값이 있는지 말이죠. 새 데이터셋을 만났을 때 기술통계의 숫자들과 나란히, 대개 가장 먼저 그리게 되는 그래프입니다.

R에서 이 함수는 hist()이며 한 줄이면 됩니다.

hist()로 만드는 첫 히스토그램

200명의 키를 시뮬레이션해 봅시다 - 평균 170cm, 표준편차 10의 정규분포입니다(set.seed()rnorm()이 하는 일은 난수를 참고하세요):

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

hist(heights)

R이 알아서 구간을 고르고 종 모양으로 쌓인 막대를 그립니다: 145cm 근처의 낮은 막대에서 시작해 160대를 거쳐 올라가고, 170 근처에서 정점을 찍은 뒤 190을 지나며 대칭적으로 떨어집니다. 세로축에는 "Frequency"(원시 도수)라는 라벨이 붙고, 제목과 축 라벨은 변수 이름에서 옵니다.

기본값은 의도적으로 밋밋합니다. 흔히 쓰는 꾸미기 인자들이 여기서도 모두 동작합니다:

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

col은 막대를 채우고 border는 테두리에 색을 입힙니다 - border = "white"는 대부분의 출판물에서 보는 깔끔하게 분리된 막대 모양을 만듭니다. plot() 가이드에서 색과 제목에 대해 설명한 모든 내용이 그대로 적용됩니다.

구간 너비: breaks 인자

hist()에서 가장 중요한 인자는 breaks입니다. 구간 너비가 그래프가 들려주는 이야기를 결정하기 때문이죠. 같은 데이터, 두 가지 설정입니다:

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

breaks = 5로는 히스토그램이 너무 거칠어 모든 것이 매끄러운 봉우리 하나처럼 보입니다 - 두 번째 군집이나 데이터의 빈틈은 보이지 않게 됩니다. breaks = 30으로는 세밀한 구조가 보이지만 무작위 요동이 특징인 척하기 시작합니다. 어느 쪽도 "정답"이 아닙니다. 솔직한 방법은 몇 가지 설정을 시도해 어떤 특징이 살아남는지 보는 것입니다.

breaks는 세 가지 형태를 받습니다:

  • 숫자 - breaks = 30 - 구간 개수에 대한 제안 입니다. R이 깔끔한 경계에 맞춰 조정하므로 28개나 33개가 될 수도 있습니다. 누구나 한 번은 놀랍니다.
  • 절단점 벡터 - breaks = seq(140, 200, by = 5) - 협상 없는 정확한 구간 경계입니다. 여러 히스토그램을 비교할 때 구간을 맞춰야 한다면 이것을 쓰세요.
  • 규칙 이름 - Freedman–Diaconis를 뜻하는 breaks = "FD"는 데이터의 산포와 표본 크기에서 너비를 정하며 치우친 데이터에서도 잘 동작합니다.

밀도 히스토그램과 정규 곡선

기본적으로 막대 높이는 도수입니다(freq = TRUE). freq = FALSE로 설정하면 막대의 총 면적 이 1이 되도록 다시 스케일합니다 - 밀도 척도입니다. 모양은 그대로이고 세로축이 바뀝니다. 이렇게 하는 이유는 밀도 히스토그램이 확률밀도함수와 같은 척도에 놓이기 때문입니다. 그래서 이론적 곡선을 데이터 위에 곧바로 겹쳐 그릴 수 있습니다:

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)

add = TRUE와 함께 쓴 curve()가 기존 히스토그램 위에 종 모양 곡선을 그립니다(dnorm(x, ...) 안의 xcurve()가 채워 넣는 자리표시자이지 여러분의 변수가 아닙니다). 막대가 곡선에 잘 달라붙으면 정규 모형이 합리적이고, 곡선에서 부풀어 나오는 곳이 있다면 - 두꺼운 꼬리, 두 번째 봉우리 - 모형이 무언가를 놓치고 있는 것입니다. freq = FALSE를 빼먹으면 도수와 밀도가 다른 척도에 있기 때문에 곡선이 그래프 바닥을 따라 쓸모없이 기어갑니다.

막대 뒤의 숫자들

hist()는 그리기만 하는 것이 아니라 구간 정보를 리스트로 반환합니다. plot = FALSE를 주면 그리기를 완전히 건너뛰고 계산만 하므로, 이 예제는 바로 여기서 실행할 수 있습니다:

h$counts는 데이터로 표현된 히스토그램입니다: 각 숫자가 막대 하나의 높이죠. table(cut(...)) 줄은 텍스트 모드로 같은 일을 합니다 - cut()이 값을 구간으로 나누고 table()이 구간별로 셉니다 - 그래프를 그리기 전에, 혹은 그래프 대신 출력해 보기 좋은 점검 방법입니다. plot = FALSE 없이 할당하면(h <- hist(heights)) R은 그림을 그리고 동시에 리스트를 반환합니다. 할당만으로는 그리기가 억제되지 않습니다.

ggplot2로 만드는 히스토그램

ggplot2 버전은 breaks 대신 binwidth를 씁니다. 구간을 몇 개로 나눌지가 아니라 구간 하나가 데이터 단위로 얼마나 넓은지를 말하는 것이라 대개 더 자연스러운 조절 다이얼입니다:

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는 막대 하나가 5cm를 덮는다는 뜻입니다. ggplot2는 binwidth를 설정하지 않으면 경고를 내고 조용히 30개 구간을 기본값으로 씁니다 - 그 경고에 귀 기울이세요. 기본값이 여러분의 데이터에 맞는 너비인 경우는 드무니까요. 변수 하나를 빠르게 훑어볼 때는 hist()가 타이핑이 적고, 히스토그램에 패싯이나 그룹이 필요하거나 다른 그림들과 일관된 테마가 필요할 때 ggplot2가 값어치를 합니다.

핵심 정리

  • 히스토그램은 하나의 수치형 변수의 분포를 보여 줍니다: hist(x) 한 줄이면 끝입니다.
  • 중요한 인자는 breaks입니다 - 숫자는 제안일 뿐이고, 벡터는 정확한 경계를 정하며, "FD"는 방어 가능한 너비를 고릅니다. 항상 두 가지 이상 설정을 시도하세요.
  • freq = FALSE는 밀도 척도로 전환하며, 그래야 curve(dnorm(...), add = TRUE)로 정규 곡선을 의미 있게 겹칠 수 있습니다.
  • hist(x, plot = FALSE)는 구간을 데이터로 반환합니다($breaks, $counts, $mids). table(cut(x, breaks))가 텍스트 전용 대응물입니다.
  • ggplot2에서는 geom_histogram(binwidth = ...)을 쓰고, binwidth는 직접 설정하세요.

다음 주제: 상자그림 - 여러 그룹을 나란히 비교할 때 진가를 발휘하는 분포 그래프입니다.

자주 묻는 질문

R에서 히스토그램은 어떻게 만드나요?

수치형 벡터에 hist(x)를 호출합니다. R이 x의 범위를 구간으로 나누고 구간마다 막대를 하나씩 그리며, 막대 높이는 그 안에 들어간 값의 개수를 나타냅니다. 구간 개수를 조절하려면 breaks =를, 막대에 색을 칠하려면 col =을 추가하세요.

hist()에서 breaks 인자는 무엇을 하나요?

구간 나누기를 조절합니다. breaks = 30 같은 단일 숫자는 구간 개수에 대한 제안이고(R이 깔끔한 경계에 맞춰 반올림합니다), breaks = seq(140, 200, by = 5) 같은 벡터는 정확한 절단점을 지정하며, breaks = "FD"는 Freedman–Diaconis 규칙을 사용합니다.

R에서 히스토그램 위에 정규 곡선을 어떻게 겹쳐 그리나요?

freq = FALSE로 밀도 척도의 히스토그램을 그린 다음 curve(dnorm(x, mean = mean(data), sd = sd(data)), add = TRUE)로 곡선을 추가합니다. 도수 척도에서는 곡선이 0 근처에 쓸모없이 깔리므로 freq = FALSE가 필수입니다.

히스토그램과 막대그래프의 차이는 무엇인가요?

히스토그램은 하나의 수치형 변수를 구간으로 나누므로 가로축이 연속 척도이고 막대가 서로 붙어 있습니다. 막대그래프는 서로 다른 범주를 비교하므로 막대가 떨어져 있습니다. R에서는 숫자에 hist(), 범주 개수에 barplot()을 씁니다.

Coddy programming languages illustration

Coddy로 코딩 배우기

시작하기