Trong cái note này tôi sẽ hướng dẫn các bạn sử dụng ggplot2 để soạn một biểu đồ than (barplot) đơn giản. Mục tiêu là vẽ một biểu đồ phản ảnh số ca phản ứng phụ trước và sau khi phẫu thuật. Tôi sẽ giải thích từng bước một để các bạn có thể hiễu rõ những hàm và lệnh trong ggplot2.
Đầu tiên, chúng ta cần đến một số chương trình/package để phân tích:
library(ggplot2); library(data.table); library(readxl); library(tidyverse)
## Warning: package 'ggplot2' was built under R version 4.0.2
## Warning: package 'data.table' was built under R version 4.0.2
## Warning: package 'tidyverse' was built under R version 4.0.2
## ── Attaching packages ─────────────────────────────────────── tidyverse 1.3.1 ──
## ✓ tibble 3.1.2 ✓ dplyr 1.0.7
## ✓ tidyr 1.1.3 ✓ stringr 1.4.0
## ✓ readr 1.4.0 ✓ forcats 0.5.1
## ✓ purrr 0.3.4
## Warning: package 'tibble' was built under R version 4.0.2
## Warning: package 'tidyr' was built under R version 4.0.2
## Warning: package 'readr' was built under R version 4.0.2
## Warning: package 'dplyr' was built under R version 4.0.2
## Warning: package 'stringr' was built under R version 4.0.2
## Warning: package 'forcats' was built under R version 4.0.2
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## x dplyr::between() masks data.table::between()
## x dplyr::filter() masks stats::filter()
## x dplyr::first() masks data.table::first()
## x dplyr::lag() masks stats::lag()
## x dplyr::last() masks data.table::last()
## x purrr::transpose() masks data.table::transpose()
Bây giờ, việc đầu tiên là đọc dữ liệu từ excel vào R dùng hàm read_excel trong readxl package:
df = read_excel("~/Downloads/PTNhan data.xlsx")
head(df)
## # A tibble: 6 x 3
## Symptom Before After
## <chr> <dbl> <dbl>
## 1 Đau đầu 25 9
## 2 Nghẹt mũi 1 bên 24 9
## 3 Nghẹt mũi 2 bên 6 1
## 4 Chảy máu mũi 15 1
## 5 Chảy mũi nhầy 12 8
## 6 Đau vùng mũi 10 5
Dữ liệu này có 2 cột giá trị (Before và After). Để vẽ biểu đồ thanh cho 2 giá trị này, chúng ta cần phải hoán chuyển 2 cột dữ liệu thành 1 cột tạm gọi là “Events”, nhưng phải tạo thêm 1 cột gọi là “Time” để biết giá trị thuộc dòng nào. Chúng ta sẽ dùng hàm melt trong chương trình data.table:
# Dữ liệu df1 bây giờ có cột "Time" và "Events" thay thế cho Before và After của df
df1 = melt(df, variable.name="Time", value.name="Events", id.vars="Symptom")
## Warning in melt(df, variable.name = "Time", value.name = "Events", id.vars =
## "Symptom"): The melt generic in data.table has been passed a tbl_df and will
## attempt to redirect to the relevant reshape2 method; please note that reshape2
## is deprecated, and this redirection is now deprecated as well. To continue using
## melt methods from reshape2 while both libraries are attached, e.g. melt.list,
## you can prepend the namespace like reshape2::melt(df). In the next version, this
## warning will become an error.
head(df1)
## Symptom Time Events
## 1 Đau đầu Before 25
## 2 Nghẹt mũi 1 bên Before 24
## 3 Nghẹt mũi 2 bên Before 6
## 4 Chảy máu mũi Before 15
## 5 Chảy mũi nhầy Before 12
## 6 Đau vùng mũi Before 10
Bây giờ, chúng ta đã sẵn sàng dùng ggplot2 để vẽ biểu đồ thanh. Chúng ta dùng hàm geom_bar()
p = ggplot(data=df1, aes(x=Symptom, y=Events, fill=Time)) + geom_bar(stat="identity")
p
Vấn đề của biểu đồ này là giá trị Before và After chồng lên nhau. Nhưng chúng ta muốn phải bên cạnh nhau. Chúng ta thêm một option position trong geom_bar:
p = ggplot(data=df1, aes(x=Symptom, y=Events, fill=Time)) + geom_bar(stat="identity", position="dodge")
p
Nhưng các nhãn của trục hoành bị trùng hợp nhau nhiều quá, và do đó khó đọc. Chúng ta sẽ dùng theme() để thay đổi góc cạnh của nhãn thành 45 độ như sau:
p = p + theme(legend.position="none", axis.text.x = element_text(angle=45, hjust=1))
p
Chúng ta cũng có thể thêm giá trị cho mỗi bar bằng cách dùng hàm geom_text() như sau:
p = p + geom_text(aes(label=Events), size=2, col="white", position=position_dodge(width=0.9), vjust=1)
p
Biểu đồ xem ra ok, nhưng chúng ta phải thay đổi nhãn sang tiếng Việt bằng cách dùng lab()
p = p + labs(x="Triệu chứng", y="Số biến cố")
p
Chúng ta cũng có thể dùng theme_bw() để đơn giản hoá cái màu nền của biểu đồ:
p = p + theme_bw() + theme(legend.position="none", axis.text.x = element_text(angle=45, hjust=1))
p
Và thế là chúng ta có một biểu đồ theo ý muốn, chúng ta có thể tích hợp trong 1 hàm như sau:
ggplot(data=df1, aes(x=Symptom, y=Events, fill=Time)) + geom_bar(stat="identity", position="dodge") + geom_text(aes(label=Events), col="white", size=3, position=position_dodge(width=0.9), vjust=1) + theme_bw() + theme(legend.position="none", axis.text.x = element_text(angle=45, hjust=1)) + labs(x="Triệu chứng", y="Số biến cố")