21. Sử dụng Seaborn để vẽ các biểu đồ thống kê (Phần 3 Categorical variable)

Trong các bài trước, chúng ta đã học cách sử dụng các scatterplots và regression models để biểu diễn mối quan hệ giữa hai biến và nó thay đổi như thế nào trong các cấp của categorical variables. Tuy nhiên, những biến chính nào mà bạn quan tâm trong categorical data? Trong trường hợp này, mô hình scatterpotot và phương pháp regression sẽ không hoạt động. Có một số tùy chọnđể thể hiện mối quan hệ như vậy, mà chúng ta sẽ thảo luận trong hướng dẫn này.

Phân chia các hình vẽ để biểu diễn categorial data trong seaborn thành ba nhóm:    Thể hiện quan sát ở mỗi cấp độ (levels/classes) của categorical data (dùng phương thức swarmplot(), stripplot())

Vẽ những điểm để mô tả phân bố của dữ liệu quan sát (dùng phương thức boxplot() và violinplot()).

Vẽ những điểm, áp dụng một phép ước lượng thống kê, để chỉ ra xu hướng trung tâm và khoảng tin cậy (dùng phương thức barplot() và pointplot ()).

Tất cả các phương thức này đều chia sẻ một API cơ bản về cách chúng dùng dữ liệu, mặc dù mỗi bộ đều có các thông số cụ thể kiểm soát các chi tiết của hình vẽ được áp dụng cho dữ liệu đó. Ta sẽ đi cụ thể lần lượt từng loại đã nêu phía trên:

Để thuận tiện cho bài, trước hết ta sẽ import đủ các gói sau và load dữ liệu:

import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
import seaborn as sns
sns.set(style="whitegrid", color_codes=True)
np.random.seed(sum(map(ord, "categorical")))
titanic = sns.load_dataset("titanic")
tips = sns.load_dataset("tips")
iris = sns.load_dataset("iris")

 

Cột dữ liệu của tips là: total_bill, tip, sex, smoker, day, time, size.

Cột dữ liệu của iris là :sepal_length, sepal_width, petal_length, petal_width,   species

Loại một: swarmplot(), stripplot()

Một cách đơn giản để chỉ ra các giá trị của một số biến định lượng trên các cấp của một categorical variable là sử dụng stripplot(), nó sẽ vẽ ra một scatterplot cho trường hợp một trong các biến là categorical variable:

sns.stripplot(x="day", y="total_bill", data=tips);

plt.show()

 

Các điểm scatterpotot sẽ chồng lên nhau. Điều này làm cho việc quan sát phân phối dữ liệu hết sức khó khăn. Một giải pháp dễ dàng là điều chỉnh các vị trí (chỉ theo trục biểu diễn biến kiểu categorical) bằng cách sử dụng một số “jitter” ngẫu nhiên:

sns.stripplot(x="day", y="total_bill", data=tips, jitter=True);

plt.show()

 

Hoặc, cách tiếp cận khác sẽ sử dụng hàm swarmplot(), đặt vị trí mỗi điểm scatterplot trên trục biểu diễn biến kiểu categorical với một thuật toán để tránh các điểm chồng chéo nhau:

sns.swarmplot(x="day", y="total_bill", data=tips);

plt.show()

Khi sử dụng swarmplot(), ta có thể lồng thêm một phân loại bằng cách sử dụng tham số hue. Cụ thể trong ví dụ tiếp theo chính là chỉ rõ mỗi điểm scatterplot là male hay female.
sns.swarmplot(x="day", y="total_bill", hue="sex", data=tips);

plt.show()

Loại thứ 2: boxplot() và violinplot()

Tại một điểm nhất định, phương pháp scatterplot trở nên giới hạn trong thông tin mà nó có thể cung cấp về phân bố các giá trị trong mỗi loại. Có một số cách để tóm tắt thông tin này giúp dễ dàng so sánh giữa các levels/classes. Chúng tôi tổng hợp một số phương pháp mà chúng ta đã thảo luận để nhanh chóng so sánh qua một số loại phân phối.

Đầu tiên là Boxplots(). Hàm này cho thấy 3/4 giá trị của phân bố cùng với các giá trị nổi trội. Các “râu hay whiskers” mở rộng đến các điểm nằm trong 1.5 IQR (Interquartile Ranges) của 1/4 dưới và trên. Thống kê giả định rằng các giá trị của bạn được nhóm lại xung quanh một số giá trị trung tâm. IQR cho biết sự phân tán dữ liệu quanh giá trị trung tâm; nó cũng có thể được sử dụng để nói khi một số các giá trị khác là “quá xa” từ giá trị trung tâm. Những điểm “quá xa xôi” này được gọi là “outliers”, bởi vì “nằm ngoài” phạm vi mà chúng ta mong đợi.

sns.boxplot(x="day", y="total_bill", hue="time", data=tips)

plt.show()

Tương tự, thay vì nhóm dữ liệu theo “Lunch” và “Dinner” ta muốn nhóm dữ liệu theo ngày bình thường và cuối tuần. Để làm việc này ta có thể transform dataframe của tips thêm một cột “weekend” bằng cách sau:

tips["weekend"] = tips["day"].isin(["Sat", "Sun"])

Sau đó vẽ như bình thường

sns.boxplot(x="day", y="total_bill", hue="weekend", data=tips);

plt.show()

Một phương pháp tiếp cận khác là violinplot(), kết hợp một boxplot() với kernel density estimation, thành phần được giới thiệu trong bài trước, đồng thời ta cũng có thể tùy chỉnh các tham số trong kernel density estimation như tham số bw = smooth bandwidth, tham khảo ý nghĩa của tham số tại: https://en.wikipedia.org/wiki/Kernel_density_estimation.

plt.title("bw is default")
sns.violinplot(x="total_bill", y="day", hue="weekend", data=tips);

plt.show()

 

Quan sát thêm ý nghĩa của bw.

plt.title("bw equals 0.05")

sns.violinplot(x="total_bill", y="day", hue="weekend", data=tips,bw=.05,);

plt.show()

 

 

Tham số split trong violinplot() còn giúp ta biểu diễn KDE khi categorical variable chỉ có 2 levels/classes. Cùng so sánh 2 cách vẽ sau, ta sẽ thấy split giúp tối ưu về không gian trên hình vẽ.

plt.title("split is false")
sns.violinplot(x="total_bill", y="day", hue="sex", data=tips,bw=.5,split = False);
plt.show()

 

 

Kết hợp biểu diễn loại 1 và loại 2 với nhau:

Như kết hợp ( stripplot(), swarmplot() ) với  ( boxplot(), violinplot() )

sns.violinplot(x="total_bill", y="day", hue="sex", data=tips,bw=.5,split = True,inner=None);

sns.swarmplot(y="day", x="total_bill", data=tips, color="w", alpha=.5);

plt.show()

 

Loại thứ 3: barplot() và pointplot ()

Thay vì hiển thị phân phối trong mỗi danh mục (categorical variable), bạn có thể muốn hiển thị xu hướng trung tâm của các giá trị. Seaborn có hai cách chính để hiển thị thông tin này, nhưng quan trọng hơn, API cơ bản cho các chức năng này giống hệt nhau đối với các hàm được thảo luận ở trên.

Một phong cách quen thuộc của plotđể hoàn thành mục tiêu này là một bar plot. Trong seaborn, hàm barplot() hoạt động trên một tập dữ liệu đầy đủ và mô tả một ước lượng (mặc định là sử dụng trung bình cộng – mean). Khi có nhiều quan sát trong mỗi loại, nó cũng sử dụng bootstrapping để tính khoảng tin cậy xung quanh ước lượng bằng cách sử dụng error bars:

Trong phần này ta làm việc với dữ liệu titanic, dataframe của nó có các cột sau: who, adult, male, deck, embark,_town, alive, alone

sns.barplot(x="sex", y="survived", hue="class", data=titanic);

plt.show()

 

Biểu đồ cho thấy tỉ lệ sống cho nữ cao hơn hẳn so với nam (trending).

Một trường hợp đặc biệt cho bar plot là khi bạn muốn hiển thị số lượng quan sát trong mỗi loại hơn là tính toán thống kê cho một biến thứ hai. Trong seaborn, thật dễ dàng để làm như vậy qua phương thức countplot():

sns.countplot(x="deck", data=titanic, palette="YlGnBu",hue="class")

plt.show()

 

Một kiểu thay thế để hiển thị thông tin giống nhau được cung cấp bởi phương thức pointplot(). Hàm này cũng mã hóa giá trị ước lượng tương ứng bằng với chiều cao trên trục, nhưng thay vì hiển thị một thanh đầy đủ nó chỉ vẽ ra điểm ước lượng và khoảng tin cậy. Ngoài ra, pointplot() kết nối các điểm từ cùng một loại hue với nhau, điều này làm cho bạn dễ dàng nhìn thấy mối quan hệ chính đang thay đổi như thế nào với hàm của một biến số thứ hai, bởi vì mắt của bạn khá giỏi trong việc thu thập sự khác nhau về độ dốc:

sns.pointplot(x="sex", y="survived", hue="class", data=titanic);

plt.show()

 

Kết Luận

Kết thúc bài học này đã khép lại một chuỗi các bài về sử dụng Seaborn để biểu diễn các biểu đồ thống kê cho các loại biến khác nhau. Bài học này tập trung vào loại dữ liệu kiểu Categorical, bạn đọc cần nhớ một số phương thức nổi bật như swarmplot, stripplot, violinplot, boxplot, pointplot, barplot và đặc biệt ngữ cảnh sử dụng chúng để có thể biểu đạt được dữ liệu chính xác nhất.

 

Để lại một bình luận

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *