Khóa học
Giới thiệu
Với facetting, bạn có thể tạo các biểu đồ nhiều khung (multi-panel) và kiểm soát cách thang đo của một khung liên hệ với thang đo của khung khác.
Sử dụng Facet đơn giản
Nếu bạn đã quen với ggplot2, bạn sẽ biết cấu trúc cơ bản của một lời gọi tới hàm ggplot(). Để bắt đầu với ggplot2, bạn có thể xem khóa học ggplot2 của chúng tôi. Khi gọi ggplot, bạn cung cấp nguồn dữ liệu, thường là một data frame, rồi yêu cầu ggplot ánh xạ các biến khác nhau trong nguồn dữ liệu tới các thuộc tính thẩm mỹ khác nhau, như vị trí trục x hoặc y hay màu sắc của điểm hoặc cột. Với facets, bạn có thêm một cách để ánh xạ các biến. Để minh họa, bạn sẽ sử dụng bộ dữ liệu sau, bao gồm một số chỉ số kinh tế cho một số quốc gia. Phần lớn là các biến thể của GDP, Tổng sản phẩm quốc nội của mỗi quốc gia.
print(econdata)
## Country GDP_nom GDP_PPP GDP_nom_per_capita GDP_PPP_per_capita
## 1 USA 19390600 19390600 59501 59495
## 2 Canada 1652412 1769270 45077 48141
## 3 China 12014610 23159107 8643 16807
## 4 Japan 4872135 5428813 38440 42659
## 5 France 2583560 2835746 39869 43550
## 6 Germany 3684816 4170790 44550 50206
## 7 Sweden 3684816 520937 53218 51264
## 8 Ireland 333994 343682 70638 72632
## GNI_per_capita Region
## 1 58270 North America
## 2 42870 North America
## 3 8690 Asia
## 4 38550 Asia
## 5 37970 Europe
## 6 43490 Europe
## 7 52590 Europe
## 8 55290 Europe
Các biến sau có trong dữ liệu:
Country: Tự giải thích!
GDP_nom: Tổng sản phẩm quốc nội theo giá danh nghĩa bằng USD
GDP_PPP: Tổng sản phẩm quốc nội đã điều chỉnh theo sức mua tương đương
GDP_nom_per_capita: Tổng sản phẩm quốc nội theo giá danh nghĩa bằng USD tính trên đầu người
GDP_PPP_per_capita: Tổng sản phẩm quốc nội đã điều chỉnh theo sức mua tương đương tính trên đầu người
GNI_per_capita: Tổng thu nhập quốc dân của mỗi quốc gia tính trên đầu người.
Region: khu vực trên thế giới nơi quốc gia đó tọa lạc.
Đầu tiên, hãy vẽ một biểu đồ cột đơn giản về GDP danh nghĩa của mỗi quốc gia.
ggplot(econdata, aes(x=Country, y=GDP_nom))+
geom_bar(stat='identity', fill="forest green")+
ylab("GDP (nominal)")

Bạn cũng có thể vẽ một biến khác, GDP đã điều chỉnh theo PPP.
ggplot(econdata, aes(x=Country, y=GDP_PPP))+
geom_bar(stat='identity', fill="forest green")+
ylab("GDP (PPP)")

Điều này cho bạn một biểu đồ thứ hai, tách biệt, tương tự biểu đồ trước nhưng sử dụng biến khác. Giả sử bạn muốn vẽ cả GDP (danh nghĩa) và GDP (PPP) cùng nhau. Bạn sẽ dùng facetting để làm điều đó. Trước hết, bạn cần định dạng lại dữ liệu, chuyển từ dạng "rộng" với mỗi biến ở một cột sang dạng "dài", trong đó bạn dùng một cột cho giá trị đo và một cột khóa cho biết mỗi hàng đang dùng thước đo nào.
econdatalong <- gather(econdata, key="measure", value="value", c("GDP_nom", "GDP_PPP"))
Khi dữ liệu đã ở định dạng này, bạn có thể sử dụng biến khóa để vẽ với facets. Hãy dựng một biểu đồ đơn giản, hiển thị cả GDP danh nghĩa (từ biểu đồ đầu) và GDP (PPP) (từ biểu đồ thứ hai). Để làm vậy, bạn chỉ cần sửa mã để thêm +facet_wrap() và chỉ định rằng ~measure, biến khóa của chúng ta, sẽ được dùng để facet.
ggplot(econdatalong, aes(x=Country, y=value))+
geom_bar(stat='identity', fill="forest green")+
facet_wrap(~measure)

Cách này hoạt động, nhưng bạn sẽ thấy tên quốc gia bị dồn chật. Hãy sắp xếp lại các khung.
Tùy chỉnh bố cục và sắp xếp lại
Lệnh facet_wrap() sẽ tự động chọn số cột. Bạn có thể chỉ định trực tiếp bằng ncol=, như sau:
ggplot(econdatalong, aes(x=Country, y=value))+
geom_bar(stat='identity', fill="forest green")+
facet_wrap(~measure, ncol=1)

Bạn có thể nhận ra rằng các quốc gia trên trục x ở trên được sắp theo thứ tự chữ cái. Nếu muốn thay đổi, cách dễ nhất là đặt lại các mức (levels) của nhân tố Country. Hãy thực hiện việc sắp xếp lại này, sắp các quốc gia theo thứ tự GDP danh nghĩa tăng dần.
econdata$Country <- factor(econdata$Country, levels= econdata$Country[order(econdata$GDP_nom)])
econdatalong <- gather(econdata, key="measure", value="value", c("GDP_nom", "GDP_PPP"))
ggplot(econdatalong, aes(x=Country, y=value))+
geom_bar(stat='identity', fill="forest green")+
facet_wrap(~measure, ncol=1)

Bạn cũng có thể tùy chỉnh thêm, như chuyển nhãn facet sang bên trái bằng tham số strip.position.
ggplot(econdatalong, aes(x=Country, y=value))+
geom_bar(stat='identity', fill="forest green")+
facet_wrap(~measure, ncol=1, strip.position = "left")

Gắn nhãn cho Facet
Bạn có thể đã thấy các facet có tiêu đề ngắn đơn giản, lấy từ các mức của nhân tố measure. Hãy chỉnh gọn và đặt nhãn dễ nhìn hơn cho các facet. Để làm vậy, bạn sẽ tạo một hàm labeller đơn giản, variable_labeller, trả về tên phù hợp khi được yêu cầu một trong các giá trị của variable_names. Sau đó, bạn truyền hàm này vào tham số labeller của facet_wrap.
variable_names <- list(
"GDP_nom" = "GDP (nominal)" ,
"GDP_PPP" = "GDP (purchasing power parity)"
)
variable_labeller <- function(variable,value){
return(variable_names[value])
}
ggplot(econdatalong, aes(x=Country, y=value))+
geom_bar(stat='identity', fill="forest green")+
facet_wrap(~measure, ncol=1, labeller=variable_labeller)

Tùy chỉnh thang đo và không gian
Hãy dựng một biểu đồ facet lớn hơn, sử dụng từng thước đo kinh tế.
econdatalong <- gather(econdata, key="measure", value="value", c( "GDP_nom" , "GDP_PPP" ,"GDP_nom_per_capita", "GDP_PPP_per_capita" ,"GNI_per_capita"))
variable_names <- list(
"GDP_nom" = "GDP (nominal)" ,
"GDP_PPP" = "GDP (purchasing power parity)",
"GDP_nom_per_capita" = "GDP (nominal) per capita",
"GDP_PPP_per_capita" = "GDP (purchasing power parity) per capita",
"GNI_per_capita" = "GNI per capita"
)
variable_labeller <- function(variable,value){
return(variable_names[value])
}
ggplot(econdatalong, aes(x=Country, y=value))+
geom_bar(stat='identity', fill="forest green")+
facet_wrap(~measure, ncol=1, labeller= variable_labeller)+
scale_y_continuous(breaks = pretty(econdatalong$value, n = 10))

Thế này thì không ổn chút nào! Bạn không thể thấy giá trị ở ba khung. Tại sao vậy? Hãy xem dữ liệu gốc để hiểu lý do.
summary(econdata)
## Country GDP_nom GDP_PPP GDP_nom_per_capita
## Ireland:1 Min. : 333994 Min. : 343682 Min. : 8643
## Canada :1 1st Qu.: 2350773 1st Qu.: 1457187 1st Qu.:39512
## France :1 Median : 3684816 Median : 3503268 Median :44814
## Germany:1 Mean : 6027118 Mean : 7202368 Mean :44992
## Sweden :1 3rd Qu.: 6657754 3rd Qu.: 8919260 3rd Qu.:54789
## Japan :1 Max. :19390600 Max. :23159107 Max. :70638
## (Other):2
## GDP_PPP_per_capita GNI_per_capita Region
## Min. :16807 Min. : 8690 Asia :2
## 1st Qu.:43327 1st Qu.:38405 Europe :4
## Median :49174 Median :43180 North America:2
## Mean :48094 Mean :42215
## 3rd Qu.:53322 3rd Qu.:53265
## Max. :72632 Max. :58270
##
Nếu xem từng cột, bạn sẽ thấy giá trị ở mỗi cột trải rộng qua vài bậc độ lớn. Mặc định, facetting sẽ dùng cùng giới hạn và phạm vi cho cả trục X và Y. Để thay đổi, bạn có thể thêm đoạn này vào mã facetting: scales="free_y" để mỗi facet dùng một thang đo y độc lập.
ggplot(econdatalong, aes(x=Country, y=value))+
geom_bar(stat='identity', fill="forest green")+
facet_wrap(~measure, scales="free_y", ncol=1, labeller= variable_labeller)

Tốt hơn nhiều. Mỗi facet giờ có trục y độc lập.
Dùng Facet để tạo phân nhóm
Bạn có thể đã nhận thấy bộ dữ liệu còn có biến Region, cho biết quốc gia đó thuộc khu vực nào. Bạn có thể dùng biến này để tô màu các cột theo khu vực như sau:
ggplot(econdatalong, aes(x=Country, y=value, fill=Region))+
geom_bar(stat='identity')+
facet_wrap(~measure, scales="free_y", ncol=1, labeller= variable_labeller)

Tuy nhiên, điều này hơi rối. Sẽ tốt hơn nếu bạn có thể đặt mỗi khu vực vào một khung phụ riêng? Với facetting, bạn có thể! Ở đây bạn sẽ dùng facet_grid thay vì facet_wrap, vì nó giúp ánh xạ facets theo hai biến, Region và measure, trong đó hai biến này trải theo các hàng và cột của một lưới biểu đồ. Lưu ý bạn cũng đặt scales="free" và space="free", cho phép các khung khác nhau chiếm lượng không gian khác nhau. Bạn cũng cần tạo một hàm labeller mới, để tạo nhãn cho cả hàng và cột.
variable_names <- list(
"GDP_nom" = "GDP \n(nominal)" ,
"GDP_PPP" = "GDP \n(PPP)",
"GDP_nom_per_capita" = "GDP (nominal)\n per capita",
"GDP_PPP_per_capita" = "GDP (PPP)\n per capita",
"GNI_per_capita" = "GNI \nper capita"
)
region_names <- levels(econdata$Region)
variable_labeller2 <- function(variable,value){
if (variable=='measure') {
return(variable_names[value])
} else {
return(region_names)
}
}
ggplot(econdatalong, aes(x=Country, y=value, fill=Region))+
geom_bar(stat='identity')+
facet_grid(measure~Region, scales="free", space="free_x", labeller= variable_labeller2)

Bây giờ thì rõ ràng hơn nhiều! Mỗi khu vực có một cột khung riêng, và mỗi thước đo có một hàng cột riêng.
Vậy là kết thúc hướng dẫn này. Hy vọng bạn thấy thú vị khi tìm hiểu về facets.
Nếu muốn tìm hiểu thêm về facets, hãy học khóa Trực quan hóa Dữ liệu lớn với Trelliscope của DataCamp.
Xem thêm Bắt đầu với Tidyverse: Hướng dẫn của chúng tôi.