막대그래프는 범주를 비교합니다
막대그래프는 "각각 얼마나?"에 답합니다 - 범주마다 막대 하나이고 막대 길이가 그 범주의 값을 나타냅니다. R에서 base 함수는 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는 막대를 가로축을 따라 눕힙니다. 이름이 긴 범주가 많을 때 가장 친절한 배치입니다 - 라벨마다 자기 막대 옆의 한 줄을 차지하므로 회전이 필요 없습니다.
막대그래프인가 히스토그램인가?
검색자들이 이 둘을 끊임없이 헷갈리므로 30초를 들일 가치가 있습니다: 막대그래프 는 서로 구별되는 범주 를 비교합니다 - 축이 라벨의 집합이고 막대가 떨어져 있으며 순서를 바꿔도 됩니다. 히스토그램 은 하나의 수치형 변수 를 구간으로 나눕니다 - 축이 연속 척도이고 구간이 연속된 간격이라 막대가 붙어 있으며 순서를 바꾸는 것은 말이 되지 않습니다. 열에 단어가 들어 있다면("Yes", "Chrome", "Q3") barplot(table(x))을, 측정값이 들어 있다면(키, 가격, 응답 시간) 히스토그램과 hist(x)를 쓰세요.
ggplot2: geom_col vs geom_bar
ggplot2 버전에는 두 개의 geom이 있으며, 세는 작업이 이미 끝났는지에 따라 나뉩니다:
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)을 추가하세요.
R에서 barplot()과 hist()의 차이는 무엇인가요?
barplot()은 서로 구별되는 범주를 비교합니다 - 범주마다 막대 하나이고 막대가 떨어져 있습니다. hist()는 하나의 수치형 변수를 연속된 구간으로 나눕니다 - 축이 연속 척도이므로 막대가 붙어 있습니다. 변수가 단어라면 barplot(table(x))을, 숫자라면 hist(x)를 쓰세요.
ggplot2에서 geom_bar와 geom_col 중 무엇을 써야 하나요?
geom_bar()는 대신 세어 줍니다 - 원시 관측값을 주면 범주별로 집계합니다. geom_col()은 이미 계산한 값을 그립니다 - 막대마다 한 행과 높이 열을 주면 됩니다. 이미 집계된 데이터를 geom_bar()에 주는 것이 전형적인 실수이며, 그런 데이터에는 geom_col()이 필요합니다.