經(jīng)??吹胶枚嗤瑢W(xué)說(shuō)學(xué)了pandas卻不知道怎么用。在跟著別人的案例學(xué)習(xí)的時(shí)候,跟著敲代碼感覺(jué)很簡(jiǎn)單??墒窃趯?shí)際操作中,拿到一份數(shù)據(jù)集,卻不知道從何下手。這種情況主要是因?yàn)闆](méi)有一個(gè)完整的思路來(lái)貫穿自己的分析過(guò)程,得到的分析結(jié)果也是東一塊,西一塊的湊起來(lái),讓用戶(hù)覺(jué)得分析的不透徹、不到位。
其實(shí)數(shù)據(jù)分析很簡(jiǎn)單,除去技術(shù)以外,一個(gè)完整的數(shù)據(jù)分析報(bào)告其實(shí)是在講一個(gè)完整的故事。你的目的就是用邏輯和數(shù)據(jù)來(lái)說(shuō)明你的觀(guān)點(diǎn)。而一份有價(jià)值的數(shù)據(jù)報(bào)告除了故事的邏輯經(jīng)得起推敲以外,重要的是你的客戶(hù)能從數(shù)據(jù)中發(fā)現(xiàn)經(jīng)營(yíng)或者業(yè)務(wù)問(wèn)題,能提供改善的建議。
因此,對(duì)于一份數(shù)據(jù)分析報(bào)告,
第一,要明確自己的分析目的和服務(wù)的對(duì)象
第二,就是要掌握一些常用的套路,這個(gè)是技術(shù)層面的東西,也是我們這一次要分享的。
下面我們來(lái)用一個(gè)具體案例來(lái)說(shuō)明這些常用的套路。
我們用的數(shù)據(jù)集是一份建筑公司的混泥土強(qiáng)度數(shù)據(jù)。背景是這個(gè)公司的銷(xiāo)售最近經(jīng)常收到一些客戶(hù)投訴,告知 他們家的混泥土強(qiáng)度變化太大。而他們自己因?yàn)轭A(yù)算有限,生產(chǎn)部門(mén)提出增加一些強(qiáng)度檢測(cè)設(shè)備時(shí)沒(méi)有采納。我們的目的就是用這份數(shù)據(jù)集看看:
- 產(chǎn)品的強(qiáng)度是否真的變化大
- 生產(chǎn)過(guò)程中哪些因素對(duì)產(chǎn)品的強(qiáng)度影響大?
- 能有什么方案改善
- 首先導(dǎo)入必要的庫(kù),和數(shù)據(jù)集
我們主要是pandas和matplot/seabron進(jìn)行分析和可視化。在導(dǎo)入之后我會(huì)習(xí)慣性的同時(shí)輸出一下各個(gè)庫(kù)的版本,核對(duì)一下開(kāi)發(fā)環(huán)境
# 先導(dǎo)入必要的計(jì)算包并查看版本,最好將pandas升級(jí)到0.24以上
import numpy as np
import pandas as pd
import matplotlib as mpl
import seaborn as sns
import matplotlib.pyplot as plt
for model in np,pd,mpl,sns:
print(model.__name__, model.__version__)
>>>
numpy 1.19.5
pandas 1.2.4
matplotlib 3.3.4
seaborn 0.11.1
另外,為了做出的圖美觀(guān)一點(diǎn),我們可以使用plt.style設(shè)置圖形的樣式。 這里我喜歡使用bmh和ggplot風(fēng)格。
# 去掉警告,不影響程序運(yùn)行
import warnings
warnings.filterwarnings('ignore')
plt.style.use('bmh') #圖形顯示風(fēng)格, ggplot或者bmh, 比默認(rèn)的好看
#省去plt.show(),直接出圖
%matplotlib inline
之后在導(dǎo)入數(shù)據(jù)。導(dǎo)入完之后都是df.head查看一下前五行,目的是了解一下數(shù)據(jù)集包含哪些字段,同時(shí)也驗(yàn)證一下數(shù)據(jù)集是否有問(wèn)題。本次的數(shù)據(jù)集和字段含義如下:

原數(shù)據(jù)集中的字段名稱(chēng)(列明)太長(zhǎng),我們可以將其簡(jiǎn)化,變化后期展示:
# 簡(jiǎn)化字段名稱(chēng)
df.columns = ['水泥含量', '高爐礦渣含量', '粉煤灰量', '含水量', '減水劑含量', \
'粗骨料含量', '細(xì)骨料含量', '齡期', '強(qiáng)度/Mpa']
df.head()

改完后清爽許多了
- 下面是本次的重點(diǎn),我們看看有哪些套路幫助我們分析
套路一: 基本的數(shù)據(jù)查看
數(shù)據(jù)集導(dǎo)入之后,我們要對(duì)數(shù)據(jù)集有個(gè)大概的了解,比如多少行(一般何樣本數(shù)量一直)多少列(每個(gè)樣本的字段/特征數(shù)量),每一列取值的大概范圍等。
在這里我喜歡用df.info和describe兩個(gè)命令來(lái)解決
- df.info 可以輸出總體的數(shù)據(jù)量以及每個(gè)字段的數(shù)據(jù)類(lèi)型
- df.describe是pandas中我最喜歡的一個(gè)功能之一,可以輸出所有數(shù)值型字段的均值標(biāo)準(zhǔn)差等
>>>df.info()
>>>
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1030 entries, 0 to 1029
Data columns (total 9 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 水泥含量 1030 non-null float64
1 高爐礦渣含量 1030 non-null float64
2 粉煤灰量 1030 non-null float64
3 含水量 1030 non-null float64
4 減水劑含量 1030 non-null float64
5 粗骨料含量 1030 non-null float64
6 細(xì)骨料含量 1030 non-null float64
7 齡期 1030 non-null int64
8 強(qiáng)度/Mpa 1030 non-null float64
dtypes: float64(8), int64(1)
memory usage: 72.5 KB

通過(guò)df.describe 我們可以發(fā)現(xiàn):
- 粉煤灰/高爐礦渣/減水劑的含量可以為0, 且有至少25%的混凝土中含量為0
- 因?yàn)槲覀兊哪康氖亲罱K產(chǎn)品的強(qiáng)度,我們重點(diǎn)關(guān)注一下最后一列強(qiáng)度的情況,包括均值最大值最小值標(biāo)準(zhǔn)差等,上面都能看到
我們?cè)趯⑿枰攸c(diǎn)分析的強(qiáng)度值單獨(dú)拿出來(lái)看一看
# 查看強(qiáng)度的分布情況
plt.figure(figsize=(15,6))
plt.subplot(121)
df['強(qiáng)度/Mpa'].plot(kind = 'hist', width = 3.5)
plt.xlabel('強(qiáng)度/Mpa', fontproperties="SimSun", fontsize=13) # 中文字體顯示
plt.title('產(chǎn)品強(qiáng)度的概率密度分布',fontproperties="SimSun", fontsize=15)
plt.subplot(122)
plt.boxplot(df['強(qiáng)度/Mpa'])
plt.title('強(qiáng)度的箱線(xiàn)圖',fontproperties="SimSun", fontsize=15)

因?yàn)閺?qiáng)度是一個(gè)單一的變量,我們可以使用折線(xiàn)圖(變化缺失)、概率密度圖(分布情況)、箱線(xiàn)圖等進(jìn)行展示。對(duì)于折線(xiàn)圖,通常會(huì)有一個(gè)時(shí)間維度來(lái)查看變量隨著時(shí)間的變化的變化趨勢(shì),這里數(shù)據(jù)集中沒(méi)有時(shí)間數(shù)據(jù)。我們就用概率分布和箱線(xiàn)圖來(lái)查看,從中我們可以發(fā)現(xiàn):
- 第一張圖中,由1000多個(gè)樣本組成的概率分布,大概可以看到強(qiáng)度數(shù)值成正態(tài)分布,均值大概位置30-40之間,但是有個(gè)別強(qiáng)度較大(大于70),遠(yuǎn)離均值形成一個(gè)長(zhǎng)尾趨勢(shì)
- 在箱線(xiàn)圖中,直接將大于80的那一部分樣本作為異常值來(lái)處理。這個(gè)也說(shuō)明一開(kāi)始的客戶(hù)投訴——最近的產(chǎn)品強(qiáng)度不穩(wěn)定,也就是有一些產(chǎn)品有超規(guī)現(xiàn)象。
知識(shí)鏈接 【箱線(xiàn)圖】
箱線(xiàn)圖也稱(chēng)盒須圖,盒圖等,常用于直觀(guān)地識(shí)別數(shù)據(jù)中異常值(離群點(diǎn))和判斷數(shù)據(jù)離散分布情況,了解數(shù)據(jù)分布狀態(tài)。在箱線(xiàn)圖中,盒子的部分是上下四分位數(shù)之間的數(shù)據(jù),盒子中間的橫線(xiàn)代表中位數(shù)。另外需要注意箱線(xiàn)圖里面的極大值(上邊緣值)有時(shí)候并非最大值,極小值(下邊緣值)也不是最小值。如果數(shù)據(jù)有存在離群點(diǎn)即異常值,他們超出最大或者最小觀(guān)察值,此時(shí)將離群點(diǎn)以“圓點(diǎn)”形式進(jìn)行展示。如上圖中強(qiáng)度大于80Mpa的部分樣本
套路二:各個(gè)自變量和因變量的相關(guān)性分析
這個(gè)是主要內(nèi)容。我們的主要目的就是想了解最終的混凝土強(qiáng)度和哪些變量最相關(guān),從而找到一些問(wèn)題的原因和改善的方法。在這里我們主要有定性的散點(diǎn)圖查看和定量的相關(guān)系數(shù)計(jì)算。
我們分成3個(gè)部分來(lái)完成這些分析
1 單變量數(shù)據(jù)分布情況
我們首先對(duì)這8個(gè)自變量也用箱線(xiàn)圖查看一下,看看每個(gè)自變量的數(shù)據(jù)分布情況:

這張圖看起來(lái)要比上面的describe功能直觀(guān)的多,同時(shí)我們也能發(fā)現(xiàn)對(duì)于齡期這個(gè)變量有很多異常值,這些產(chǎn)品的齡期異常的高,這個(gè)是否是問(wèn)題呢?這個(gè)就需要結(jié)合業(yè)務(wù)來(lái)分析了。
# 先用箱線(xiàn)圖查看一下各個(gè)變量的分布
plt.figure(figsize=(20,16)) # 設(shè)置一張較大的圖,容得下8張小圖
for i, feature in enumerate(list(df.columns[:-1])):
plt.subplot(2,4,i+1)
plt.boxplot(df[feature], widths=0.2)
plt.title(feature, fontproperties="SimSun", fontsize=13)
2 自變量和因變量的相關(guān)性定性分析
我們先用用散點(diǎn)圖進(jìn)行直觀(guān)的展示。分析一下數(shù)據(jù)我們知道數(shù)據(jù)集中每個(gè)樣本共有8個(gè)自變量(特征)和一個(gè)因變量。我們把每個(gè)自變量和因變量做出一個(gè)散點(diǎn)圖來(lái)展示。
# 定性分析: 各個(gè)變量與因變量的pair-plot散點(diǎn)圖查看
plt.figure(figsize=(20,16)) # 設(shè)置一張較大的圖,容得下8張小圖
for i, feature in enumerate(list(df.columns[:-1])):
plt.subplot(3,3,i+1)
plt.scatter(df[feature], df['強(qiáng)度/Mpa'])
plt.xlabel(feature, fontproperties="SimSun", fontsize=13 )
plt.ylabel('強(qiáng)度/Mpa',fontproperties="SimSun", fontsize=13)
上面的代碼中,我們一次性將8個(gè)自變量和因變量的三點(diǎn)輸出在一張大圖上,便于查看,結(jié)果如下:

從這些圖大概可以得知:
- 水泥含量cement和superplasticizer(減水劑含量)和強(qiáng)度有較好的正相關(guān)關(guān)系
- water(含水量)和強(qiáng)度有較好的負(fù)相關(guān)關(guān)系
- 礦渣和齡期和強(qiáng)度沒(méi)有關(guān)系,并且齡期好像還是一個(gè)離散型的變量
上面通過(guò)圖形來(lái)進(jìn)行直觀(guān)展示,缺乏精確量化指標(biāo)。下面我們進(jìn)行定量分析,計(jì)算每個(gè)自變量和因變量的相關(guān)系數(shù)。
3 相關(guān)系數(shù)計(jì)算,定量分析
Python中計(jì)算相關(guān)性非常簡(jiǎn)單,直接df.corr即可。默認(rèn)采用的是pearson系數(shù)。

我們重點(diǎn)關(guān)注 表格中的最后一列,即各個(gè)自變量和強(qiáng)度的相關(guān)系數(shù)。
從中我們可以看到:
- 水泥含量和減水劑含量與強(qiáng)度有一定的相關(guān)性
- 齡期和強(qiáng)度也有一定的相關(guān)性,這個(gè)和我們從上面的散點(diǎn)圖得到的結(jié)論有一些不一致。
這個(gè)也從側(cè)面說(shuō)明了對(duì)一個(gè)具體問(wèn)題,定量和定性分析都是需要的,有時(shí)候圖形雖然直觀(guān),但是不夠精確。
套路三 進(jìn)一步挖掘
在這里我們需要思考如何從數(shù)據(jù)中找到更多的線(xiàn)索,挖掘出更多的價(jià)值。主要思路有:
- 我們有8個(gè)自變量,我們是否可以考慮按照某些變量的取值將樣本分組,每一組單獨(dú)考慮而不是放在一起呢?即將某些變量的取值固定下來(lái)在計(jì)算其他指標(biāo),這個(gè)是一個(gè)常用的思路
- 考慮各個(gè)自變量之間的相關(guān)性。上面我們重點(diǎn)關(guān)注了自變量和因變量之間的關(guān)系,有時(shí)候我們的自變量之間有時(shí)候也是有一定相關(guān)性的。如果兩個(gè)自變量之間相關(guān)性較強(qiáng),我們可以考慮將其中一個(gè)變量去掉來(lái)為后期的機(jī)器學(xué)習(xí)簡(jiǎn)化模型
由于篇幅關(guān)系,我們僅用第一條舉例說(shuō)明。
我們考慮一下為啥套路二中定性和定量分析得出的關(guān)于齡期和強(qiáng)度關(guān)系不太一樣?其實(shí)思考一下就可以發(fā)現(xiàn)主要是因?yàn)辇g期里面有很多值較大,這些離群點(diǎn)作為噪音干擾了分析。那我們就把這些值去掉在看看。
因?yàn)辇g期的取值比較離散化,直至統(tǒng)計(jì)各個(gè)取值的個(gè)數(shù)
df['齡期'].value_counts()
>>>
28 425
3 134
7 126
56 91
14 62
90 54
100 52
180 26
91 22
365 14
270 13
360 6
120 3
1 2
Name: 齡期, dtype: int64
可以看到28天將近一半,取值在56天以上的樣本比較少,我們將齡期取值在56天以?xún)?nèi)的樣本放在一起單獨(dú)分析看看
(df['齡期'] <= 56).sum() / len(df['齡期']) #統(tǒng)計(jì)齡期在56天以?xún)?nèi)的占比
>>> 0.8155339805825242
# age <= 56有超過(guò)80%的樣本,單獨(dú)分析
df_age56 = df[df['齡期'] <= 56]
df_age56.shape
>>> (840, 9)
上面創(chuàng)建一個(gè)新的Dataframe,其實(shí)是將原數(shù)據(jù)集中齡期在56天以?xún)?nèi)的樣本放在一起。我們?cè)谔子蒙厦娴纳Ⅻc(diǎn)圖和相關(guān)系數(shù)計(jì)算看一看
# 先定量分析,通過(guò)pariplot查看
plt.figure(figsize=(20,16))
for i, feature in enumerate(list(df_age56.columns[:-1])):
plt.subplot(3,3,i+1)
plt.scatter(df_age56[feature], df_age56['強(qiáng)度/Mpa'])
plt.xlabel(feature,fontproperties="SimSun", fontsize=13)
plt.ylabel('強(qiáng)度/Mpa',fontproperties="SimSun", fontsize=13)

將齡期較大的樣本去除后,齡期和強(qiáng)度的相關(guān)性明朗許多了!在定量計(jì)算看一看

OK,去除噪聲后,齡期和強(qiáng)度相關(guān)性更強(qiáng)了。和上面的定性分析統(tǒng)一起來(lái)了。關(guān)于其他變量的分組分析各位可以按照此套路自己嘗試了。本次分享就到這里。
另外,本案例中用到的原始數(shù)據(jù)和代碼有需要的可以私信我獲取,謝謝!