小白學 Python 數據分析(10):Pandas (九)數據運算

人生苦短,我用 Python

前文傳送門:

小白學 Python 數據分析(1):數據分析基礎

小白學 Python 數據分析(2):Pandas (一)概述

小白學 Python 數據分析(3):Pandas (二)數據結構 Series

小白學 Python 數據分析(4):Pandas (三)數據結構 DataFrame

小白學 Python 數據分析(5):Pandas (四)基礎操作(1)查看數據

小白學 Python 數據分析(6):Pandas (五)基礎操作(2)數據選擇

小白學 Python 數據分析(7):Pandas (六)數據導入

小白學 Python 數據分析(8):Pandas (七)數據預處理

小白學 Python 數據分析(9):Pandas (八)數據預處理(2)

引言

前面我們介紹了很多關於 Pandas 的基礎操作以及拿到一份數據後首先要做的是對數據的基礎預處理。

本篇我們接著介紹當我們處理完數據後,可以對數據進行的一些計算操作。

本篇文章使用的數據為泰坦尼克的數據集,具體的數據集已經上傳至程式碼倉庫,有需要的同學可以自行取用。

數據來源是著名的 Kaggle :https://www.kaggle.com/

中國的網路訪問有些慢,建議自己想辦法,實在不行,可以加小編微信,小編有個神奇的軟體,特別好用。

在正文內容開始前,小編先把數據中的表名的中英文對照列出來:

  • PassengerId : 乘客ID
  • Survived : 是否倖存
  • Pclass : 乘客等級(1/2/3等艙位)
  • Name : 姓名
  • Sex : 性別
  • Age : 年齡
  • SibSp : 堂兄弟/妹個數
  • Parch : 父母與小孩個數
  • Ticket : 船票資訊
  • Fare : 票價
  • Cabin : 客艙
  • Embarked : 登船港口

預處理

首先,我們拿到數據的第一步是先檢查一下數據品質,通過方法 info() 看下有數據品質:

import pandas as pd    # 數據導入  data_train = pd.read_csv("train.csv")  # 數據查看  print(data_train.info())    # 輸出內容  <class 'pandas.core.frame.DataFrame'>  RangeIndex: 891 entries, 0 to 890  Data columns (total 12 columns):  PassengerId    891 non-null int64  Survived       891 non-null int64  Pclass         891 non-null int64  Name           891 non-null object  Sex            891 non-null object  Age            714 non-null float64  SibSp          891 non-null int64  Parch          891 non-null int64  Ticket         891 non-null object  Fare           891 non-null float64  Cabin          204 non-null object  Embarked       889 non-null object  dtypes: float64(2), int64(5), object(5)  memory usage: 83.7+ KB  None

上面這些數據到底說了個啥?

看過我前面文章的同學應該知道,info() 這個方法經常用作查看數據空值,很不辛,這裡有些屬性的數據不全,如:

  • Age(年齡)屬性只有714名乘客有記錄
  • Cabin(客艙)更是只有204名乘客是已知的

這裡我們進一步使用 describe() 看下這批數據的統計分析數據:

print(data_train.describe())    # 輸出內容         PassengerId    Survived      Pclass         Age       SibSp    count   891.000000  891.000000  891.000000  714.000000  891.000000  mean    446.000000    0.383838    2.308642   29.699118    0.523008  std     257.353842    0.486592    0.836071   14.526497    1.102743  min       1.000000    0.000000    1.000000    0.420000    0.000000  25%     223.500000    0.000000    2.000000   20.125000    0.000000  50%     446.000000    0.000000    3.000000   28.000000    0.000000  75%     668.500000    1.000000    3.000000   38.000000    1.000000  max     891.000000    1.000000    3.000000   80.000000    8.000000                Parch        Fare  count  891.000000  891.000000  mean     0.381594   32.204208  std      0.806057   49.693429  min      0.000000    0.000000  25%      0.000000    7.910400  50%      0.000000   14.454200  75%      0.000000   31.000000  max      6.000000  512.329200  

能看出來啥呢?

如果把目光聚焦在 mean 這一行上,可以看到大概 0.383838 的人最後獲救了,在 2 / 3 等倉的人要比 1 等倉的多得多(這不是廢話),平均年齡大概是 29.699118 (這個值計算的時候會忽略掉空值)等等。

算數運算

emmmmmmmmmm,寫到這裡小編髮現個問題,用這份數據演示算數運算屬實有點不大合適,滿臉尷尬。

小編這麼懶的人都寫到這了,肯定是不會換數據集了,各位看官就這麼湊合著看吧,先聲明一下,以下演示均無實際意義。

這一小節的標題是算數運算,那無非是加減乘除嘛,首先來看下兩列相加的示例,這裡是把堂兄弟姐妹和父母小孩加在一起,結果稍微有點意義,這個乘客的所有親屬:

print(data_train['SibSp'] + data_train['Parch'])    # 輸出內容  0      1  1      1  2      0  3      1  4      0        ..  886    0  887    0  888    3  889    0  890    0  Length: 891, dtype: int64

兩列相減,這裡我們使用這個乘客的所有親屬再加上他本身減去存活人數,示例如下:

print(data_train['SibSp'] + data_train['Parch'] + 1 - data_train['Survived'])    # 輸出內容  0      2  1      1  2      0  3      1  4      1        ..  886    1  887    0  888    4  889    0  890    1  Length: 891, dtype: int64

乘除同理,小編這裡就不演示,各位同學可以自己動手試試。

比較

這裡我們選用存活數和親屬數量做比較,幾個簡單的示例:

print(data_train['Survived'] > (data_train['SibSp'] + data_train['Parch']))    # 輸出內容  0      False  1      False  2       True  3      False  4      False         ...  886    False  887     True  888    False  889     True  890    False  Length: 891, dtype: bool

同理,這裡除了可以使用 > 還可以使用 >=!=<<= 等運算符。

統計分析

前面我們使用 describe() 這個方法自動的獲取過當前數據集的一些統計數據,那麼我們如何手動的來獲取它呢?

統計非空值

首先是 count() 統計非空值:

# 按列統計  print(data_train.count())    # 輸出內容  PassengerId    891  Survived       891  Pclass         891  Name           891  Sex            891  Age            714  SibSp          891  Parch          891  Ticket         891  Fare           891  Cabin          204  Embarked       889  dtype: int64    # 按行統計  print(data_train.count(axis=1))    # 輸出內容  0      11  1      12  2      11  3      12  4      11         ..  886    11  887    12  888    10  889    12  890    11  Length: 891, dtype: int64    # 某一列單獨統計  print(data_train['Age'].count())    # 輸出內容  714

求和

接下來是求和, sum 這個函數想必各位都在 Excel 中用過,那麼在 Pandas 中是如何使用的,請看下面的示例:

# 按列求和  print(data_train.sum())    # 輸出內容  PassengerId                                               397386  Survived                                                     342  Pclass                                                      2057  Name           Braund, Mr. Owen HarrisCumings, Mrs. John Brad...  Sex            malefemalefemalefemalemalemalemalemalefemalefe...  Age                                                      21205.2  SibSp                                                        466  Parch                                                        340  Ticket         A/5 21171PC 17599STON/O2. 31012821138033734503...  Fare                                                     28693.9  dtype: object    # 按行求和  print(data_train.sum(axis=1))    # 輸出內容  0       34.2500  1      114.2833  2       40.9250  3       95.1000  4       51.0500           ...  886    929.0000  887    939.0000  888    918.4500  889    948.0000  890    933.7500  Length: 891, dtype: float64

可以看到,在進行按列求和的時候, Pandas 把非數值類型的列直接將所有的欄位拼合在了一起,其實無太大意義。

求算數平均值

接下來是求算數平均值,這個函數是 mean() ,算數平均值有一個特點是極易受到極大極小值的影響,就比如我和小馬哥的資產平均超過了 100 億,這個其實和我基本上沒有半毛錢關係。

print(data_train.mean())    # 輸出內容  PassengerId    446.000000  Survived         0.383838  Pclass           2.308642  Age             29.699118  SibSp            0.523008  Parch            0.381594  Fare            32.204208  dtype: float64

mean() 實際是上對每一列進行了求平均值的運算,實際上可以通過 axis 參數按行獲取平均值,不過在當前的數據集毫無意義,小編這裡就不演示了。

求最大最小值

接下來是求最大最小值,在 Excel 其實可以直接通過排序來直觀的看到某一列的最大最小值,那麼,一起看一下在 Pandas 是如何獲取這兩個值:

print(data_train.max())  print('------------------------')  print(data_train.min())    # 輸出內容  PassengerId                            891  Survived                                 1  Pclass                                   3  Name           van Melkebeke, Mr. Philemon  Sex                                   male  Age                                     80  SibSp                                    8  Parch                                    6  Ticket                           WE/P 5735  Fare                               512.329  dtype: object  --------------------------------------------  PassengerId                      1  Survived                         0  Pclass                           1  Name           Abbing, Mr. Anthony  Sex                         female  Age                           0.42  SibSp                            0  Parch                            0  Ticket                      110152  Fare                             0  dtype: object

可以看到,在 Pandas 中獲取最大最小值是使用了兩個函數, max()min() ,通過字面意思大家也懂,這裡同樣要提一下是默認是按照列來獲取最大最小值,如果有需要,也可以通過參數 axis 來按照行來獲取。

中位數

相比較前面提到過的算數平均數,中位數是一個非常不錯的反應一組數據的一般情況的一個數據,不易受到極大值和極小值的影響。

在 Pandas 中,獲取中位數是使用 median() 函數:

print(data_train.median())    # 輸出內容  PassengerId    446.0000  Survived         0.0000  Pclass           3.0000  Age             28.0000  SibSp            0.0000  Parch            0.0000  Fare            14.4542  dtype: float64

同樣, median() 函數也可以通過 axis 參數來按照行進行獲取。

眾數

眾數就是出現次數最多的那個數,這裡我們使用到的函數是 mode()

print(data_train.mode())    # 輸出內容     Survived  Pclass   Sex   Age  SibSp  Parch  Fare Embarked  0         0       3  male  24.0      0      0  8.05        S    [891 rows x 12 columns]    # 單獨獲取某列眾數  print(data_train['Sex'].mode())    # 輸出內容  0    male  dtype: object

方差標準差

方差和標準差其實都是用來表示數據的離散程度,標準差是方差的平方根。

在 Pandas 中,計算方差是使用 var() 函數,而計算標準差是使用 std() 函數:

print(data_train.var())    # 輸出內容  PassengerId    66231.000000  Survived           0.236772  Pclass             0.699015  Age              211.019125  SibSp              1.216043  Parch              0.649728  Fare            2469.436846  dtype: float64    print(data_train.std())    # 輸出內容  PassengerId    257.353842  Survived         0.486592  Pclass           0.836071  Age             14.526497  SibSp            1.102743  Parch            0.806057  Fare            49.693429  dtype: float64

各位閑著沒事兒的同學可以核實一下把標準差平方一下看看是不是方差。

反正小編怕翻車,是專門核實了一下,確實沒有問題,如果哪位同學核實出來有問題,可能是小編這台電腦有問題。

求分位數

分位數是一種比中位數更加詳細的根據位置的指標,在統計學中,最常用的是四分位數:

  • 第一四分位數(Q1),又稱「較小四分位數」,等於該樣本中所有數值由小到大排列後第 25% 的數字;
  • 第二四分位數(Q2),又稱「中位數」,等於該樣本中所有數值由小到大排列後第 50% 的數字;
  • 第三四分位數(Q3),又稱「較大四分位數」,等於該樣本中所有數值由小到大排列後第 75% 的數字。

在 Pandas 中,獲取分位數是使用 quantile() 函數,但是在使用的過程中,一定要標識清楚去的分位數值:

print(data_train.quantile(0.25))  print('-----------------------------------------')  print(data_train.quantile(0.5))    # 輸出內容  PassengerId    223.5000  Survived         0.0000  Pclass           2.0000  Age             20.1250  SibSp            0.0000  Parch            0.0000  Fare             7.9104  Name: 0.25, dtype: float64  -----------------------------------------  PassengerId    446.0000  Survived         0.0000  Pclass           3.0000  Age             28.0000  SibSp            0.0000  Parch            0.0000  Fare            14.4542  Name: 0.5, dtype: float64

這裡的驗證可以對比我們前面取出來的中位數,看下是否一致就好,如果不一致,可能需要換電腦了。

相關性

相關性運算是指兩個事務之間的關聯程度,這裡我們可以使用 corr() 函數來進行相關性運算。

使用方式:

DataFrame.corr(method=’pearson’, min_periods=1)

參數說明:

method:可選值為 {‘pearson’, ‘kendall’, ‘spearman’}

  • pearson:Pearson相關係數來衡量兩個數據集合是否在一條線上面,即針對線性數據的相關係數計算,針對非線性數據便會有誤差。
  • kendall:用於反映分類變數相關性的指標,即針對無序序列的相關係數,非正太分布的數據
  • spearman:非線性的,非正太分析的數據的相關係數

我們一般比較常用的是皮爾遜相關係數:

print(data_train.corr(method='pearson'))    # 輸出內容               PassengerId  Survived    Pclass       Age     SibSp     Parch    PassengerId     1.000000 -0.005007 -0.035144  0.036847 -0.057527 -0.001652  Survived       -0.005007  1.000000 -0.338481 -0.077221 -0.035322  0.081629  Pclass         -0.035144 -0.338481  1.000000 -0.369226  0.083081  0.018443  Age             0.036847 -0.077221 -0.369226  1.000000 -0.308247 -0.189119  SibSp          -0.057527 -0.035322  0.083081 -0.308247  1.000000  0.414838  Parch          -0.001652  0.081629  0.018443 -0.189119  0.414838  1.000000  Fare            0.012658  0.257307 -0.549500  0.096067  0.159651  0.216225                     Fare  PassengerId  0.012658  Survived     0.257307  Pclass      -0.549500  Age          0.096067  SibSp        0.159651  Parch        0.216225  Fare         1.000000 

本篇內容是真的有點長,各位慢慢看吧,小編就先溜了~~~

示例程式碼

老規矩,所有的示例程式碼都會上傳至程式碼管理倉庫 Github 和 Gitee 上,方便大家取用。

示例程式碼-Github

示例程式碼-Gitee

參考

https://baike.baidu.com/item/%E5%88%86%E4%BD%8D%E6%95%B0/10064158?fr=aladdin

https://blog.csdn.net/walking_visitor/article/details/85128461