探索性數(shù)據(jù)分析(EDA)之?dāng)?shù)據(jù)可視化案例:附數(shù)據(jù)集和源碼
Python 提供了一組豐富的庫,使我們能夠快速有效地創(chuàng)建可視化。在使用 Python 進(jìn)行探索性數(shù)據(jù)分析過程中有幾種常用的可視化類型,包括:
- 條形圖(Bar charts):用于顯示不同類別之間的比較。
- 折線圖(Line charts):用于顯示一段時間內(nèi)或不同類別之間的趨勢。
- 餅狀圖(Pie charts):用于顯示不同類別的比例或百分比。
- 直方圖(Histograms):用于顯示單個變量的分布。
- 熱力圖(Heatmaps):用于顯示不同變量之間的相關(guān)性。
- 散點(diǎn)圖(Scatter plots):用于表示兩個連續(xù)變量之間的關(guān)系。
- 箱形圖(Box plots):用于顯示變量的分布和識別異常值。
使用 Python 創(chuàng)建數(shù)據(jù)可視化的一般步驟如下:
- 理解業(yè)務(wù)問題:這一步很重要,因?yàn)檫@關(guān)系到最后我們能否獲得正確的可視化結(jié)果。
- 導(dǎo)入必要的庫:如 Pandas, Seaborn, Matplotlib, Plotly。
- 加載數(shù)據(jù)集:加載需要分析和可視化的數(shù)據(jù)集。
- 數(shù)據(jù)清理和預(yù)處理:通過刪除缺失值、重復(fù)值和異常值來對數(shù)據(jù)進(jìn)行清洗和預(yù)處理。另外,將分類數(shù)據(jù)轉(zhuǎn)換為數(shù)值數(shù)據(jù)。
- 統(tǒng)計匯總:計算描述性統(tǒng)計數(shù)據(jù),如平均值、中位數(shù)、眾數(shù)、標(biāo)準(zhǔn)差和相關(guān)系數(shù),以便了解變量之間的關(guān)系。
- 數(shù)據(jù)可視化和解釋:創(chuàng)建可視化來理解數(shù)據(jù)中的分布、關(guān)系和模式。然后解釋可視化,從而獲得關(guān)于數(shù)據(jù)的啟發(fā)性見解和結(jié)論。
1. 理解業(yè)務(wù)問題
心血管疾病是全球人員死亡的主要原因。據(jù)世界衛(wèi)生組織(WHO)統(tǒng)計,每年約有1790萬人死于心臟病,其中85%的死亡是由心臟病發(fā)作和中風(fēng)引起的。
在本文中,我們將探索心臟病發(fā)病數(shù)據(jù)集(獲取方式見文末),利用 Python 為探索性數(shù)據(jù)分析創(chuàng)建數(shù)據(jù)可視化。
該數(shù)據(jù)集包含患者的各種變量數(shù)據(jù),如年齡、性別、血壓、膽固醇水平以及是否患有心臟病。我們的目標(biāo)是根據(jù)患者的醫(yī)療屬性來預(yù)測他們是否有心臟病發(fā)病的風(fēng)險。
2. 加載必要的庫
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import plotly.express as px
import plotly.graph_objects as go
from plotly.subplots import make_subplots
3. 加載數(shù)據(jù)集
heart = pd.read_csv('datasets/heart.csv')
現(xiàn)在我們已經(jīng)加載了數(shù)據(jù),讓我們看一下 DataFrame 的前幾行,對數(shù)據(jù)有一個基本的了解。
heart.head()
圖片
我們一起來看看每列的含義:
- age:患者年齡
- sex:患者性別
- cp:胸痛類型(0-典型心絞痛;1-非典型心絞痛;2-非心絞痛;3-無癥狀)
- trbps:靜息血壓(單位:毫米汞柱)
- chol:膽固醇量(毫克/分)
- fbs:空腹血糖 > 120 mg/dl(1-true;0-false)
- restecg:靜息心電圖結(jié)果
0:正常
1:ST-T波異常(T 波反轉(zhuǎn)和/或 ST 波升高或下降 > 0.05 mV)
2:根據(jù)埃斯蒂斯標(biāo)準(zhǔn)顯示可能或明確的左心室肥厚
- thalachh:達(dá)到的最大心率
- exng:運(yùn)動誘發(fā)心絞痛(1-是;0-否)
- oldpeak:前一個峰值
- slp:斜率
- caa:主要血管數(shù)量(0-3)
- thall:貧血率
- output:目標(biāo)變量(0-更低的心臟病發(fā)病率;1-更高的心臟病發(fā)病率)
我們可以看到,數(shù)據(jù)集包含14列,包括目標(biāo)列(output),它表示患者是否會心臟病發(fā)病?,F(xiàn)在我們開始創(chuàng)建可視化。
4. 數(shù)據(jù)清洗和預(yù)處理
數(shù)據(jù)清洗的目的是為后面的分析和可視化做準(zhǔn)備。比如檢測缺失值:
heart.isnull().sum().sort_values(ascending=False).head(11)
圖片
從輸出中可以看出,該數(shù)據(jù)集中不存在缺失值。接下來,我們檢測重復(fù)行:
heart.duplicated().sum()
輸出:
1
我們直接刪除重復(fù)值:
heart.drop_duplicates(keep='first', inplace=True)
輸出:
0
到此,我們的清洗工作結(jié)束。接下來我們將會計算一些統(tǒng)計匯總信息。
5. 統(tǒng)計匯總信息
heart.describe().T
圖片
從上面的統(tǒng)計信息摘要中我們可以得到的主要推論是,對于大多數(shù)列,其平均值與中位數(shù)相似(1/2百分位:50%)。
6. 數(shù)據(jù)可視化及解釋
6.1 基于性別的數(shù)據(jù)可視化
條形圖:
df = pd.crosstab(heart['output'], heart['sex'])
sns.set_style('white')
df.plot(kind='bar',
figsize=(6, 6),
color=['#c64343', '#e1d3c1'])
plt.title('Heart Attack Risk vs Sex ', fnotallow=16)
plt.xlabel('0 = Lower Risk 1 = Higher Risk', fnotallow=16)
plt.ylabel('Amount', fnotallow=16)
plt.legend(['Femal', 'Male'], fnotallow=14)
plt.xticks(rotatinotallow=0)
圖片
餅圖:
heart2 = heart.copy()
sex_mapping = {0: 'Female', 1: 'Male'}
heart2['sex'] = heart2['sex'].map(sex_mapping)
fig = px.pie(heart2,
names='sex',
template='presentation',
hole=0.6,
color_discrete_sequence=['#e1d3c1', '#c64343'])
# layout
fig.update_layout(title_text='Gender Distribution',
title_x=0.5,
fnotallow=dict(size=18),
autosize=False,
width=500,
height=500,
showlegend=False)
fig.add_annotation(dict(x=0.5, y=0.5, align='center',
xref='paper', yref='paper',
showarrow=False, font_size=22,
text="<span style='font-size: 26px; color=#555; font-family: Arial'>Gender<br></span>"))
fig.update_traces(textpositinotallow='outside', textinfo='percent+label', rotatinotallow=20)
fig.show()
圖片
解釋:男性患心臟病的風(fēng)險比女性更高。
6.2 基于年齡的數(shù)據(jù)可視化
柱狀圖:
plt.figure(figsize=(14, 8))
sns.set(font_scale=1.2)
sns.set_style('white')
sns.countplot(x=heart['age'], palette='Reds')
plt.title('Count of Patients Age', fnotallow=20)
plt.xlabel('Age', fnotallow=16)
plt.ylabel('Count', fnotallow=16)
plt.show()
圖片
直方圖+核密度圖:
sns.set(font_scale=1.3)
plt.figure(figsize=(8, 6))
sns.set_style('white')
sns.histplot(x=heart['age'], color='red', kde=True)
plt.title('Distribution of Patients Age', fnotallow=20)
plt.xlabel('Age', fnotallow=16)
plt.ylabel('Density', fnotallow=16)
plt.show()
圖片
解釋:大多數(shù)患者年齡在50-60歲之間,其中58歲的患者人數(shù)最多。
6.3 基于膽固醇水平的數(shù)據(jù)可視化
直方圖+核密度圖:
sns.set(font_scale=1.3)
sns.set_style('white')
plt.figure(figsize=(8, 6))
sns.histplot(x=heart[heart['output']==0]['chol'], color='blue', kde=True)
sns.histplot(x=heart[heart['output']==1]['chol'], color='red', kde=True)
plt.title('Heart Attack Risk vs Cholesterol', fnotallow=20)
plt.xlabel('Cholesterol Level', fnotallow=16)
plt.ylabel('Density', fnotallow=16)
plt.legend(['Lower Risk', 'Higher Risk'], fnotallow=14)
plt.show()
圖片
折線圖:
plt.figure(figsize=(8, 6))
sns.lineplot(y='chol', x='age', data=heart, color='red')
plt.title('Cholesterol with Age', fnotallow=20)
plt.xlabel('Age', fnotallow=16)
plt.ylabel('Cholesterol Level', fnotallow=16)
plt.show()
圖片
解釋:
- 大多數(shù)患者的膽固醇水平在200-300之間。
- 隨著年齡的增長,體內(nèi)的膽固醇水平很有可能增加。
6.4 基于胸痛類型的數(shù)據(jù)可視化
heart3 = heart.copy()
cp_mapping = {0: 'Typical angina', 1: 'Atypical angina',
2: 'Non-anginal pain', 3: 'Asymptomatic'}
heart3['cp'] = heart3['cp'].map(cp_mapping)
df = pd.crosstab(heart3['cp'], heart3['output'])
# Make the crosstab more visual
sns.set(font_scale=1.3)
sns.set_style('white')
df.plot(kind='bar',
figsize=(11, 7),
color=['#e1d3c1', '#c64343'])
plt.title('Heart Attack Risk vs. Chest Pain Type', fnotallow=20)
plt.xlabel('Chest Pain types', fnotallow=16)
plt.ylabel('Amount', fnotallow=16)
plt.legend(['Lower Risk', 'Higher Risk'], fnotallow=14)
plt.xticks(rotatinotallow=0)
圖片
解釋:
- 大多數(shù)患者為典型心絞痛類型。
- 非心絞痛患者心臟病發(fā)病的風(fēng)險更高。
6.5 基于相關(guān)性的數(shù)據(jù)可視化
plt.figure(figsize=(12, 10))
sns.set(font_scale=0.9)
sns.heatmap(heart.corr(), annot=True, cmap='Reds')
plt.title('Correlation Between Variables', size=15)
plt.show()
圖片
解釋:
通過熱力圖我們可以看出以下變量之間存在強(qiáng)相關(guān)性:
- 胸痛類型(cp)和目標(biāo)變量(output)
- 達(dá)到的最大心率(thalachh)和目標(biāo)變量(output)
- 斜率(slp)和目標(biāo)變量(output)
同時,我們也可以看出以下變量之間存在弱相關(guān)性:
- 前一個峰值(oldpeak)和目標(biāo)變量(output)
- 主要血管數(shù)量(caa)和目標(biāo)變量(output)
- 運(yùn)動誘發(fā)心絞痛(exng)和目標(biāo)變量(output)
7. 結(jié)論
在這篇文章中,我們使用數(shù)據(jù)可視化在數(shù)據(jù)集上做了一系列的實(shí)驗(yàn)和測試,基于各個變量對數(shù)據(jù)集做了一些分析,比如單變量分析和可視化(條形圖、餅圖、折線圖、直方圖);熱力圖可看作是雙變量分析,因?yàn)樗尸F(xiàn)了兩兩變量之間的相關(guān)性。
探索性分析(EDA)和數(shù)據(jù)可視化的主要目的是在做任何假設(shè)之前幫助我們更好的理解數(shù)據(jù),它們能夠讓我們對數(shù)據(jù)分布、匯總統(tǒng)計、變量和異常值之間的關(guān)系有一個直觀的理解。通過可視化,能夠得出一些有價值的洞見,達(dá)到輔助策略決策的目的。