Menu

R의 상자그림: 예제로 배우는 그룹별 boxplot()

R에서 boxplot()으로 상자그림 만드는 방법 - 상자와 수염 읽기, 그룹 비교를 위한 수식 인터페이스, 스타일 지정, 그리고 그 뒤의 숫자 확인하기.

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

상자그림 읽는 법

상자그림은 분포 전체를 다섯 개의 숫자로 압축해 하나의 간결한 도형으로 그립니다. 읽는 법을 배우는 데는 30초면 되니 먼저 익혀 봅시다 - 각 부분에는 정확한 의미가 있습니다:

  • 상자 안의 굵은 선중앙값 입니다: 데이터의 절반이 그 아래, 절반이 그 위에 있습니다.
  • 상자 자체사분위범위(IQR)를 나타냅니다 - 제1사분위수(데이터의 25%가 그 아래)부터 제3사분위수(75%가 그 아래)까지죠. 데이터의 가운데 절반이 상자 안에 살고 있습니다.
  • 수염 은 상자에서 뻗어 나온 선입니다. 각 수염은 상자 가장자리로부터 1.5 × IQR 이내에 있는 가장 극단적인 데이터 점까지 닿습니다 - 그러니 전체 범위가 아니라 "평범한 범위"를 덮습니다.
  • 수염 너머의 개별 점 은 상자에서 1.5 × IQR 이상 떨어진 값입니다: 이상치 의심 으로 표시되며, 셀 수 있도록 하나씩 그려집니다.

상자가 길면 데이터가 퍼져 있다는 뜻이고, 중앙값 선이 상자 안에서 한쪽으로 치우쳐 있으면 왜도를 뜻하며, 한쪽 수염 너머로 점들이 줄지어 있으면 그쪽 꼬리가 두껍다는 뜻입니다. 히스토그램은 같은 분포를 더 자세히 보여 주지만, 상자그림의 초능력은 열두 개를 나란히 놓을 수 있다는 점이며, 그래서 그룹 비교에는 바로 그 그래프입니다.

변수 하나의 상자그림

함수는 boxplot()이며, 수치형 벡터 하나라면 호출 한 번입니다:

scores <- c(52, 55, 58, 60, 61, 63, 64, 66, 68, 70, 72, 95)

boxplot(scores,
        main = "Test scores",
        ylab = "Score")

이것이 그리는 그림은 이렇습니다: 59에서 69까지의 상자, 63.5에 있는 중앙값 선, 아래로 52까지 위로 72까지 뻗은 수염, 그리고 95에 홀로 떠 있는 점 하나 - 평균과 표준편차 요약이었다면 조용히 흡수해 버렸을 이상치죠. "값 하나가 나머지와 다르다"를 즉시 보여 주는 것, 그것이 상자그림의 존재 이유입니다.

(이 장의 모든 페이지가 그렇듯 작도 호출은 정적인 예제입니다 - 아래 실행기는 텍스트 출력만 보여 줍니다. 그림을 보려면 로컬에서 실행하세요.)

그룹 비교: 수식 인터페이스

실제 일상적인 용도는 그룹마다 상자 하나를 그리는 것이며, 이를 위해 boxplot()수식 을 받습니다: y ~ group은 "group으로 나눈 y"로 읽습니다. R의 내장 데이터셋 ToothGrowth - 오렌지 주스(OJ)나 아스코르브산(VC)으로 비타민 C를 투여한 기니피그 60마리의 치아 길이 - 가 전형적인 시연 사례입니다:

boxplot(len ~ supp,
        data = ToothGrowth,
        main = "Tooth growth by supplement",
        xlab = "Supplement",
        ylab = "Tooth length")

공통 세로축 위에 두 개의 상자가 나타납니다: OJ 상자가 VC 상자보다 눈에 띄게 높고, 중앙값은 약 22 대 약 19입니다. 두 상자가 축 하나를 공유하므로 비교는 구조적으로 정직합니다 - 척도가 다른 두 그래프가 한쪽 그룹을 돋보이게 할 여지가 없습니다. 그룹 열은 팩터(또는 문자 벡터)여야 하며, 각 수준이 상자 하나가 됩니다.

수식은 중첩도 됩니다: boxplot(len ~ supp * dose, data = ToothGrowth)는 보충제와 용량 조합마다 하나씩 여섯 개의 상자를 그립니다. 상자에서 그룹 차이가 실재하는 것처럼 보일 때 자연스럽게 따라오는 질문 - 이것이 잡음 이상인가? - 에는 t-검정이 답합니다.

라벨, 색상, 그리고 가로 상자그림

스타일 인자는 base R의 작도 관례를 따릅니다. names가 상자에 라벨을 붙이고 col이 상자를 채웁니다 - 벡터를 전달하면 그룹마다 다른 색을 칠할 수 있습니다:

boxplot(len ~ supp,
        data  = ToothGrowth,
        names = c("Orange juice", "Ascorbic acid"),
        col   = c("orange", "lightblue"),
        main  = "Tooth growth by supplement",
        ylab  = "Tooth length")

값어치를 하는 스위치가 두 개 더 있습니다:

  • horizontal = TRUE는 그래프 전체를 회전시켜 상자가 가로축을 따라 놓이게 합니다. 그룹 이름이 길 때는 언제나 이렇게 하세요 - 세로 라벨은 서로 부딪히지만 가로 라벨은 읽기 좋게 유지됩니다.
  • notch = TRUE는 각 중앙값 주위에 홈을 파냅니다. 두 그룹의 홈이 겹치지 않으면 중앙값이 다를 가능성이 높습니다. 검정이 아니라 시각적 힌트로 받아들이세요.

상자 뒤의 숫자들

그래프가 그리는 모든 것은 여러분이 출력해 볼 수 있는 숫자에서 나옵니다. quantile()은 다섯 숫자 요약을 주고, boxplot.stats()는 그래프가 사용하는 값을 정확히 줍니다 - 이상치까지 포함해서요. 이 예제는 여기서 바로 실행할 수 있습니다:

둘은 쌍둥이가 아니라 사촌입니다: quantile()은 진짜 최솟값과 최댓값을 보고하지만, s$stats수염 에서 끝납니다 - 1.5 × IQR 울타리 안의 가장 극단적인 점까지죠. 둘 사이의 간극이 정확히 s$out이며, 여기서는 홀로 있는 95입니다. 누군가 "저 이상치 점들은 어느 행인가요?"라고 물으면 x[x %in% boxplot.stats(x)$out] - 또는 울타리 값으로 필터링하는 것 - 이 답이 됩니다.

ggplot2로 만드는 상자그림

ggplot2에서는 그룹화가 수식이 아니라 미적 매핑으로 들어갑니다:

library(ggplot2)

ggplot(ToothGrowth, aes(x = supp, y = len, fill = supp)) +
    geom_boxplot() +
    labs(title = "Tooth growth by supplement",
         x = "Supplement", y = "Tooth length")

같은 두 상자에 범례와 테마가 덤으로 붙습니다. 그래프가 커질수록 ggplot2 버전이 더 잘 확장됩니다 - dose로 패싯을 나누고, geom_jitter(width = 0.1)로 원시 점을 겹쳐도 코드는 선언적으로 남습니다. 분석 도중의 일회성 비교라면 boxplot(y ~ g, data = df)가 여전히 가장 빨리 칠 수 있는 코드입니다.

핵심 정리

  • 상자의 해부학: 중앙값 선, 상자 = IQR, 수염 = 1.5 × IQR 이내의 가장 극단적인 점, 그 너머의 점 = 이상치 의심.
  • 변수 하나에는 boxplot(x), 하나의 정직한 공통 척도 위에서 그룹을 나란히 비교할 때는 boxplot(y ~ group, data = df).
  • names, 그룹별 col 벡터로 꾸미고, 라벨이 길면 horizontal = TRUE를 쓰세요.
  • boxplot.stats(x)$stats$out은 숫자로 표현된 그래프입니다 - 그래프가 가리키는 이상치를 추출할 때 사용하세요.
  • ggplot2: 그룹을 xfill에 매핑한 geom_boxplot().

다음 주제: 산점도 - 한 변수의 분포에서 두 변수의 관계로 넘어갑니다.

자주 묻는 질문

R에서 상자그림은 어떻게 만드나요?

상자 하나를 그리려면 수치형 벡터에 boxplot(x)를 호출하고, 그룹마다 상자를 나란히 그리려면 수식 인터페이스 boxplot(y ~ group, data = df)를 사용하세요. 둘 다 base R에 포함되어 있어 패키지가 필요 없습니다.

상자그림의 각 부분은 무엇을 뜻하나요?

상자 안의 굵은 선은 중앙값입니다. 상자는 제1사분위수부터 제3사분위수까지의 사분위범위를 나타냅니다. 수염은 상자에서 사분위범위의 1.5배 이내에 있는 가장 극단적인 데이터 점까지 뻗어 나가며, 수염을 넘어가는 값은 개별 점으로 그려져 이상치로 의심됩니다.

R에서 그룹별 상자그림은 어떻게 만드나요?

수식을 사용합니다: boxplot(len ~ supp, data = ToothGrowth)supp의 수준마다 상자를 하나씩 그립니다. 그룹 변수는 팩터나 문자형 열이어야 하며, 각 수준이 공통 척도 위의 상자 하나가 됩니다.

상자그림이 보여 주는 이상치는 어떻게 찾나요?

boxplot.stats(x)$out은 그래프가 수염 바깥의 점으로 그릴 값들을 정확히 반환하고, boxplot.stats(x)$stats는 상자를 이루는 다섯 숫자 - 수염 끝, 힌지, 중앙값 - 를 알려 줍니다.

Coddy programming languages illustration

Coddy로 코딩 배우기

시작하기