Biểu đồ cột so sánh các nhóm phân loại
Biểu đồ cột (bar chart) trả lời câu hỏi "mỗi loại bao nhiêu?": mỗi nhóm một cột, chiều dài cột thể hiện giá trị của nhóm đó. Trong R, hàm cơ bản là barplot(), và đầu vào của nó chỉ đơn giản là một vector chiều cao. Đặt tên cho các phần tử của vector và các tên đó sẽ thành nhãn dưới các cột:
visits <- c(Mon = 42, Tue = 51, Wed = 47, Thu = 60, Fri = 78)
barplot(visits,
main = "Store visits by day",
ylab = "Visits")
Năm cột màu xám, gắn nhãn theo ngày, tăng dần từ thứ Hai khiêm tốn đến đỉnh vào thứ Sáu, cao gần gấp đôi. Không cần cài gì, không cần cấu hình gì: nếu bạn tạo được một vector có tên, bạn vẽ được nó.
Các trình soạn thảo chạy được trên trang này chỉ hiển thị đầu ra dạng văn bản, nên các lời gọi barplot() ở đây là những đoạn code tĩnh để dán vào một phiên R trên máy bạn. Còn bước đếm trước đó thì chạy được bình thường, và đó mới là bước quan trọng nhất.
Quy trình thực tế: table() trước, barplot() sau
Trong thực tế, bạn hiếm khi có sẵn các chiều cao đã đếm gọn gàng. Bạn có một cột thô chứa nhãn phân loại, mỗi hàng là một câu trả lời khảo sát, một đơn hàng hay một người dùng, và việc đếm mới là phần việc thật sự. table() làm việc đó trong một lời gọi, và đầu ra của nó là một vector số đếm có tên, đúng thứ mà barplot() cần:
Sau đó biểu đồ chỉ cần thêm một dòng:
barplot(sort(t, decreasing = TRUE),
main = "Survey responses",
ylab = "Count")
Hai bước đó, table() rồi barplot(), là quy trình vẽ biểu đồ cột phổ biến nhất trong R. Sắp xếp bảng trước là một cải tiến rẻ: các cột xếp theo chiều cao dễ đọc hơn các cột xếp theo bảng chữ cái, trừ khi các nhóm có thứ tự tự nhiên (ngày, tháng, mức liều). Khi đó, một factor với các level được sắp đúng thứ tự sẽ ngăn table() xếp chúng theo bảng chữ cái. Với những cột cần tổng hợp thật sự, tức tổng hoặc trung bình theo nhóm thay vì đếm số hàng, hãy làm bước group-by-summarize trước rồi đưa kết quả cho barplot().
Nhãn và kiểu dáng
Nhãn thường lấy từ tên của vector, nhưng names.arg sẽ ghi đè chúng, rất hữu ích khi mã trong dữ liệu không phù hợp để người xem đọc:
barplot(visits,
names.arg = c("Monday", "Tuesday", "Wednesday",
"Thursday", "Friday"),
col = "steelblue",
border = NA,
main = "Store visits by day",
las = 2)
coltô màu các cột; truyền một vector để tô màu từng cột riêng, nhưng đừng mặc định dùng cầu vồng: màu sắc nên mang ý nghĩa, như làm nổi bật đúng cột bạn đang nói đến.border = NAbỏ viền các cột cho gọn gàng hơn.las = 2xoay nhãn trục vuông góc với trục, cách khắc phục khi tên nhóm dài đè lên nhau. Kết hợp với lề dưới rộng hơn (par(mar = c(8, 4, 4, 2))) nếu tên thực sự dài.
Cột nhóm và cột chồng từ ma trận
Để thể hiện hai chiều phân loại cùng lúc, chẳng hạn doanh số theo kênh theo quý, hãy đưa cho barplot() một ma trận. Mỗi cột của ma trận trở thành một vị trí trên trục phân loại, còn các hàng trở thành các cột con:
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 đặt hai kênh đứng sát cạnh nhau trong mỗi quý, tốt nhất khi bạn muốn so sánh trực tiếp các kênh. Kiểu chồng mặc định nhấn mạnh tổng của mỗi quý, với phần chia nhỏ hiển thị bên trong mỗi cột; nó trung thực với tổng nhưng khiến các đoạn bên trong khó so sánh giữa các cột, vì đường gốc của chúng bị dịch chuyển. legend.text = rownames(sales) thêm chú giải giúp cả hai phiên bản dễ đọc.
Thêm một tùy chọn nữa: horiz = TRUE đặt các cột nằm dọc theo trục ngang. Đây là bố cục dễ chịu nhất cho nhiều nhóm có tên dài: mỗi nhãn nằm trên một dòng riêng cạnh cột của nó, không cần xoay.
Biểu đồ cột hay histogram?
Người ta nhầm hai loại này liên tục, và sự khác biệt đáng để bỏ ra ba mươi giây: biểu đồ cột so sánh các nhóm phân loại riêng biệt: trục là một tập nhãn, các cột tách rời nhau, và sắp xếp lại chúng là hợp lệ. Histogram chia một biến số thành các khoảng: trục là một thang liên tục, các cột chạm nhau vì các khoảng nối tiếp nhau, và sắp xếp lại chúng sẽ vô nghĩa. Nếu cột dữ liệu chứa chữ ("Yes", "Chrome", "Q3"), bạn cần barplot(table(x)). Nếu nó chứa số đo (chiều cao, giá, thời gian phản hồi), bạn cần histogram và hist(x).
ggplot2: geom_col và geom_bar
Phiên bản ggplot2 có hai geom, phân biệt bởi việc dữ liệu đã được đếm sẵn hay chưa:
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() là table() được tích hợp vào biểu đồ: nó nhận mỗi quan sát một hàng và tự đếm. geom_col() nhận dữ liệu đã tổng hợp sẵn và ánh xạ một cột y thành chiều cao cột, tương đương với barplot() cổ điển. Đưa dữ liệu đã đếm sẵn cho geom_bar() là cái bẫy kinh điển của người mới: nó đếm số hàng (mỗi nhóm một hàng) và mọi cột đều cao bằng nhau.
Điều cần nhớ
barplot(heights)vẽ một vector có tên, vàtable(x)tạo ra đúng hình dạng đó từ dữ liệu phân loại thô, nênbarplot(table(x))là cách viết cốt lõi.- Sắp xếp bảng (hoặc đặt level cho factor) trước khi vẽ; thứ tự các cột là một phần của thông điệp.
- Một ma trận cho ra cột nhóm (
beside = TRUE) hoặc cột chồng (mặc định); hãy thêmlegend.text = rownames(m). names.arg,col,las = 2vàhoriz = TRUElo phần nhãn; cột ngang tốt nhất cho tên dài.- Nhóm phân loại → biểu đồ cột; khoảng số → histogram. Trong ggplot2: hàng thô →
geom_bar(), chiều cao đã tính →geom_col().
Tiếp theo: chính ggplot2, bộ ngữ pháp dựng nên tất cả các biểu đồ này và nhiều biểu đồ khác nữa từ cùng vài thành phần ghép nối được.
Câu hỏi thường gặp
Làm sao vẽ biểu đồ cột trong R?
Gọi barplot() trên một vector chiều cao. Hãy đặt tên cho các phần tử của vector, hoặc tạo nó bằng table() (đầu ra vốn đã có tên), và mỗi phần tử sẽ thành một cột có nhãn: barplot(table(df$category)).
Làm sao vẽ biểu đồ cột nhóm hoặc cột chồng trong R?
Truyền vào một ma trận. Mỗi cột của ma trận trở thành một vị trí trên trục phân loại; beside = TRUE vẽ các hàng thành những cột đứng cạnh nhau (cột nhóm), còn mặc định beside = FALSE thì xếp chồng chúng lên nhau. Thêm legend.text = rownames(m) để người đọc phân biệt được các hàng.
barplot() và hist() trong R khác nhau thế nào?
barplot() so sánh các nhóm phân loại riêng biệt: mỗi nhóm một cột, các cột tách rời nhau. hist() chia một biến số thành các khoảng liên tiếp: các cột chạm nhau vì trục là một thang liên tục. Nếu biến của bạn là chữ, bạn cần barplot(table(x)); nếu là số, bạn cần hist(x).
Nên dùng geom_bar hay geom_col trong ggplot2?
geom_bar() đếm giúp bạn: đưa cho nó các quan sát thô và nó sẽ đếm từng nhóm. geom_col() vẽ các giá trị bạn đã tính sẵn: đưa cho nó mỗi cột một hàng cùng một cột chiều cao. Dùng geom_bar() cho dữ liệu đã đếm sẵn là lỗi kinh điển; trường hợp đó cần geom_col().