《pandas數據分析》(一)——數據基礎操作

語言: CN / TW / HK

主要目的是通過真實的數據,以實戰的方式瞭解數據分析的流程和熟悉數據分析python的基本操作。通過正式的數據分析的實戰教學,完成kaggle上泰坦尼克的任務,實戰數據分析全流程。

分為三個部分,大致可以分為:數據基礎操作,數據清洗與重構,建模和評估。

  1. 第一部分:我們獲得一個要分析的數據,我要學會如何加載數據,查看數據,然後學習Pandas的一些基礎操作,最後開始嘗試探索性的數據分析。
  2. 第二部分:當我們可以比較熟練的操作數據並認識這個數據之後,我們需要開始數據清洗以及重構,將原始數據變為一個可用好用的數據,為之後放入模型做準備
  3. 第三部分:我們根據任務需求不同,要考慮建立什麼模型,我們使用流行的sklearn庫,建立模型。對於一個模型的好壞,我們是需要評估的,之後我們會評估我們的模型,對模型做優化。

1 數據載入及初步觀察

1.1 載入數據

數據集下載 https://www.kaggle.com/c/titanic/overview

1.1.1 任務一:導入numpy和pandas

```Python

寫入代碼

import pandas as pd import numpy as np ```

【提示】如果加載失敗,學會如何在你的python環境下安裝numpy和pandas這兩個庫


1.1.2 任務二:載入數據

(1) 使用相對路徑載入數據
(2) 使用絕對路徑載入數據

```Python

寫入代碼

data=pd.read_csv('train.csv') data.head(5)

寫入代碼

data=pd.read_csv(r'C:\Users\87479\Desktop\my_data_analysis\第一章項目集合\train.csv') data.head(5) ```

image.png 【提示】相對路徑載入報錯時,嘗試使用os.getcwd()查看當前工作目錄。
【總結】加載的數據是所有工作的第一步,我們的工作會接觸到不同的數據格式(eg:.csv;.tsv;.xlsx),但是加載的方法和思路都是一樣的,在以後工作和做項目的過程中,遇到之前沒有碰到的問題,要多多查資料,使用googel,瞭解業務邏輯,明白輸入和輸出是什麼。


1.1.3 任務三:每1000行為一個數據模塊,逐塊讀取

```python

寫入代碼

設置chunksize參數,來控制每次迭代數據的大小

chunker = pd.read_csv("train.csv",chunksize=1000) for piece in chunker: print(type(piece)) # print(len(piece)) #891 ```

【思考】什麼是逐塊讀取?為什麼要逐塊讀取呢?

當我們處理大型文件的時候,讀入文件的一個小片段或者按小塊遍歷文件是比較好的做法


1.1.4 任務四:將表頭改成中文,索引改為乘客ID (對於某些英文資料,我們可以通過翻譯來更直觀的熟悉我們的數據)

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

```Python

寫入代碼

data.rename(columns={'PassengerId':'乘客ID','Survived':'是否倖存','Pclass':'乘客等級(1/2/3等艙位)', 'Name':'乘客姓名','Sex':'性別','Age':'年齡','SibSp':'堂兄弟/妹個數','Parch':'父母與小孩個數','Ticket':'船票信息', 'Fare':'票價','Cabin':'客艙','Embarked':'登船港口'},inplace=True) data.head(5) ```

image.png 【思考】所謂將表頭改為中文其中一個思路是:將英文列名錶頭替換成中文。還有其他的方法嗎?


1.2 初步觀察

導入數據後,你可能要對數據的整體結構和樣例進行概覽,比如説,數據大小、有多少列,各列都是什麼格式的,是否包含null等

1.2.1 任務一:查看數據的基本信息

寫入代碼

```Python

查看每列的類型,dataframe的屬性dtypes可以返回表示每列數據名稱及類型的列表:

print(data.dtypes) ```

image.png ```Python

獲取每列數據的統計特徵(eg:總行數,列數據的平均值、標準差,etc)

使用:dataframe.describe()即可查看每列數據的

''' (1)總行數統計count (2)平均值mean (3)標準差std (4)最小值min (5)25%分位值“25%” (6)50%分位值“50%” (7)75%分位值“75%” (8)最大值max ''' data.describe() ```

image.png Python ''' 注意:方法describe()只統計(沒有任何參數的情況下)數據類型(numeric-typed數據類型,例如int,float等)列的統計特徵,並且會自動NaN值。 如果我們想查看所有列的統計特徵(即包括非數據類型的列,例如object類型的列),就需要在describe()方法中添加參數(include = “all”) ''' data.describe(include='all')

image.png Python ''' 獲取指定列的統計學特徵 使用如下語句: dataframe[[‘column1’, ‘column2’, ‘column3’]].describe() ''' data[['乘客ID','年齡']].describe()

image.png python ''' 使用方法info()來查看dataframe的簡介描述 使用如下語句: dataframe.info() 此方法打印有關dataframe的信息,包括索引dtype和列、非空值和內存使用情況。 ''' data.info()

image.png python ''' 查看數據的行數及列數 通過屬性shape,獲取數據集的(行數,列數) ''' print(data.shape)

image.png python ''' 是否包含null ''' print(data.isnull())

image.png


1.2.2 任務二:觀察表格前10行的數據和後15行的數據

```python

寫入代碼

data.head(10) ```

image.png

```python

寫入代碼

data.tail(15) ```

image.png

1.2.3 任務三:判斷數據是否為空,為空的地方返回True,其餘地方返回False

```python

寫入代碼

''' 1、判斷數值是否為空,可以用pd.isna,pd.isnull,np.isnan; 2、判斷字符串是否為空,可以用pd.isna,pd.isnull; 3、判斷時間是否為空,可以用pd.isna,pd.isnull,np.isnat; 4、判斷轉換類型後的字符串,空值也轉換成了字符串nan,所以不能用常規方法判斷了,直接判斷字符串是否相等即可。 ''' data.isnull().head(20)

data.isna()

```

image.png

【總結】上面的操作都是數據分析中對於數據本身的觀察


1.3 保存數據

1.3.1 任務一:將你加載並做出改變的數據,在工作目錄下保存為一個新文件train_chinese.csv

```python

寫入代碼

注意:不同的操作系統保存下來可能會有亂碼。大家可以加入encoding='GBK' 或者 encoding = 'utf-8'

data.to_csv('train_chinese.csv') df=pd.read_csv('train_chinese.csv') df.head(5) ```

image.png 【總結】數據的加載以及入門,接下來就要接觸數據本身的運算,我們將主要掌握numpy和pandas在工作和項目場景的運用。


總結: 數據分析的第一步,加載數據我們已經學習完畢了。當數據展現在我們面前的時候,我們所要做的第一步就是認識他,今天我們要學習的就是瞭解字段含義以及初步觀察數據

2 Pandas基礎

1.4 知道你的數據叫什麼

我們學習pandas的基礎操作,那麼上一節通過pandas加載之後的數據,其數據類型是什麼呢?

開始前導入numpy和pandas

python import numpy as np import pandas as pd


1.4.1 任務一:pandas中有兩個數據類型DateFrame和Series,通過查找簡單瞭解他們。然後自己寫一個關於這兩個數據類型的小例子🌰[開放題]

```python

寫入代碼

''' 維數 名稱 描述 1 Series 帶標籤的一維同構數組 2 DataFrame 帶標籤的,大小可變的,二維異構表格

為什麼有多個數據結構?

Pandas 數據結構就像是低維數據的容器。比如,DataFrame 是 Series 的容器,Series 則是標量的容器。使用這種方式,可以在容器中以字典的形式插入或刪除對象。 ''' sdata = {'Ohio': 35000, 'Texas': 71000, 'Oregon': 16000, 'Utah': 5000} example_1 = pd.Series(sdata) print(example_1) data = {'state': ['Ohio', 'Ohio', 'Ohio', 'Nevada', 'Nevada', 'Nevada'], 'year': [2000, 2001, 2002, 2001, 2002, 2003],'pop': [1.5, 1.7, 3.6, 2.4, 2.9, 3.2]} example_2 = pd.DataFrame(data) print(example_2) ```

image.png


1.4.2 任務二:根據上節課的方法載入"train.csv"文件

```python

寫入代碼

data=pd.read_csv('train.csv') ```


1.4.3 任務三:查看DataFrame數據的每列的名稱

```python

寫入代碼

現在有一個dataframe對象df1,查看索引使用使用df1.index,查看列名使用df1.columns,查看所有的值為df1.values。

print(list(data))

data.columns ```

image.png


1.4.4 任務四:查看"Cabin"這列的所有值[有多種方法]

```python

寫入代碼

data['Cabin']

寫入代碼

data.Cabin ```

image.png


1.4.5 任務五:加載文件"test_1.csv",然後對比"train.csv",看看有哪些多出的列,然後將多出的列刪除

經過我們的觀察發現一個測試集test_1.csv有一列是多餘的,我們需要將這個多餘的列刪去

```python

寫入代碼

data1=pd.read_csv('test_1.csv') data1.head(5) ```

image.png

```python

寫入代碼

del data1['a'] data1.head(5) ```

image.png 【思考】還有其他的刪除多餘的列的方式嗎?

```python

# 思考回答

import datacompy

compare = datacompy.Compare(data, data1)

# Compare 參數:

# df1: 數據框1

# df2: 數據框2

# join_columns: 指定索引的列名,默認“None”,可以傳入數組,比如:['key', 'AdID']

# on_index: 是否要開啟索引,開啟之後不需要指定 join_columns,默認“False”

# abs_tol: 絕對公差,默認“0”

# rel_tal: 相對公差,默認“0”

# df1_name: 報告中數據框1的名字,默認“df1”

# df2_name: 報告中數據框2的名字,默認“df2”

# ignore_spaces: 是否忽略空格,默認“False”

# ignore_case: 是否忽略大小寫,默認“False”

print(compare.matches()) # 最後判斷是否相等,返回 bool

print(compare.report()) # 打印報告詳情,返回 string

# print(compare.sample_mismatch('用户數')) # 取出不相同的某一列數據,返回 dataframe

```

1.4.6 任務六: 將['PassengerId','Name','Age','Ticket']這幾個列元素隱藏,只觀察其他幾個列元素

```python

寫入代碼

''' DataFrame.drop(labels=None, axis=0, index=None, columns=None, level=None, inplace=False, errors='raise')

這是drop函數的所有參數 labels是指要刪除的標籤,一個或者是列表形式的多個,axis是指處哪一個軸,columns是指某一列或者多列,level是指等級,針對多重索引的情況,inplaces是否替換原來的dataframe ''' data.drop(['PassengerId','Name','Age','Ticket'],axis=1).head(5)

data.head(5)

```

image.png 【思考】對比任務五和任務六,是不是使用了不一樣的方法(函數),如果使用一樣的函數如何完成上面的不同的要求呢?

【思考回答】 如果想要完全的刪除你的數據結構,使用inplace=True,因為使用inplace就將原數據覆蓋了,所以這裏只是單純的隱藏

1.5 篩選的邏輯

表格數據中,最重要的一個功能就是要具有可篩選的能力,選出我所需要的信息,丟棄無用的信息。

下面我們還是用實戰來學習pandas這個功能。


1.5.1 任務一: 我們以"Age"為篩選條件,顯示年齡在10歲以下的乘客信息。

```python

寫入代碼

data[data['Age']<10].head(5) ```

image.png


1.5.2 任務二: 以"Age"為條件,將年齡在10歲以上和50歲以下的乘客信息顯示出來,並將這個數據命名為midage

```python

寫入代碼

midage=data[(data['Age']>10) & (data['Age']<50)] #此時的索引已經不連續了,需要重置索引 midage.head(100) ``` image.png 【提示】瞭解pandas的條件篩選方式以及如何使用交集和並集操作


1.5.3 任務三:將midage的數據中第100行的"Pclass"和"Sex"的數據顯示出來

```python

寫入代碼

''' 此時DataFrame或Series類型的數據不再是連續的索引,可以使用reset_index()重置索引。

''' midage = midage.reset_index(drop=True) midage.head(100) midage.loc[[100],['Pclass','Sex']] ```

image.png


1.5.4 任務四:使用loc方法將midage的數據中第100,105,108行的"Pclass","Name"和"Sex"的數據顯示出來

```python

寫入代碼

midage.loc[[100,105,108],['Pclass','Name','Sex']]

midage.loc[[100,105,108],'Pclass':'Sex'] #相同寫法

```

image.png


1.5.5 任務五:使用iloc方法將midage的數據中第100,105,108行的"Pclass","Name"和"Sex"的數據顯示出來

```python

寫入代碼

midage.iloc[[100,105,108],[2,3,4]] ```

image.png

【思考】對比ilocloc的異同

  • loc函數主要基於行標籤和列標籤(x_label、y_label)進行索引:使用loc函數,索引的是字符串,前後都要取,是屬於“前閉後閉”的情況
  • iloc函數主要基於行索引和列索引(index,columns) 都是從 0 開始:而且,iloc函數索引的數據是int整型,因此是Python默認的前閉後開。注意只能説int型,也就是數字,輸入字符的話是會報錯的。(注意索引都是默認從0開始的),而且傳入的必須是一個列表

總結: 在前面我們已經學習了Pandas基礎,知道利用Pandas讀取csv數據的增刪查改,今天我們要學習的就是探索性數據分析,主要介紹如何利用Pandas進行排序、算術計算以及計算描述函數describe()的使用。

3 探索性數據分析

開始之前,導入numpy、pandas包和數據

```python

加載所需的庫

import numpy as np import pandas as pd

載入之前保存的train_chinese.csv數據,關於泰坦尼克號的任務,我們就使用這個數據

data=pd.read_csv('train_chinese.csv') data.head(5) ```

image.png

1.6 瞭解你的數據嗎?

1.6.1 任務一:利用Pandas對示例數據進行排序,要求升序

```python

自己構建一個都為數字的DataFrame數據

''' 我們舉了一個例子 pd.DataFrame() :創建一個DataFrame對象 np.arange(8).reshape((2, 4)) : 生成一個二維數組(2*4),第一列:0,1,2,3 第二列:4,5,6,7 index=[2,1] :DataFrame 對象的索引列 columns=['d', 'a', 'b', 'c'] :DataFrame 對象的索引行 ''' data1=np.arange(8).reshape((2,4))

print(data)

index=[2,1] columns=['d','a','b','c'] df=pd.DataFrame(data=data1,index=index,columns=columns) df.head(2) ```

image.png

【代碼解析】

pd.DataFrame() :創建一個DataFrame對象

np.arange(8).reshape((2, 4)) : 生成一個二維數組(2*4),第一列:0,1,2,3 第二列:4,5,6,7

index=['2, 1] :DataFrame 對象的索引列

columns=['d', 'a', 'b', 'c'] :DataFrame 對象的索引行

【問題】:大多數時候我們都是想根據列的值來排序,所以將你構建的DataFrame中的數據根據某一列,升序排列

```python

回答代碼

''' 升序排列是把數據從小到大進行排列,而降序排列是把數據從大到小進行排列 DataFrame.sort_values(by, ascending=True, inplace=Flase )

參數説明: by: 字符串或者List<字符串>,單列排序或者多列排序 ascending:bool或者list,升序還是降序,如果是list對應by的多列 默認為True升序排序,為False降序排序 inplace:是否修改原始的DataFrame ''' df.sort_values(by='a',ascending=True).head(2) ```

image.png

【總結】下面將不同的排序方式做一個總結

1.讓行索引升序排序

```python

代碼

''' axis=0代表往跨行(down),而axis=1代表跨列(across) 使用0值表示沿着每一列或行標籤/索引值向下執行方法 使用1值表示沿着每一行或者列標籤橫向執行對應的方法 ''' df.sort_index(axis=0,ascending=True).head(2) ```

image.png

axis的理解

20200720111708736.png

2.讓列索引升序排序

```python

代碼

df.sort_index(axis=1,ascending=True).head(2) ```

image.png

3.讓列索引降序排序

```python

代碼

df.sort_index(axis=1,ascending=False).head(2) ```

image.png

4.讓任選兩列數據同時降序排序

```python

代碼

df.sort_values(by=['a','c'],ascending=False).head(2) ```

image.png

1.6.2 任務二:對泰坦尼克號數據(trian.csv)按票價和年齡兩列進行綜合排序(降序排列),從這個數據中你可以分析出什麼?

```python

代碼

data.sort_values(by=['年齡','票價'],ascending=False).head(20)

data.sort_values(by=['票價', '年齡'], ascending=False).head(20) ```

image.png

【思考】排序後,如果我們僅僅關注年齡和票價兩列。根據常識我知道發現票價越高的應該客艙越好,所以我們會明顯看出,票價前20的乘客中存活的有14人,這是相當高的一個比例,那麼我們後面是不是可以進一步分析一下票價和存活之間的關係,年齡和存活之間的關係呢?當你開始發現數據之間的關係了,數據分析就開始了。

對於多列排序的理解

python d = {'A': [3, 6, 6, 7, 9], 'B': [2, 5, 8, 0, 0]} df = pd.DataFrame(data=d) print('排序前:\n', df) ''' 排序前: A B 0 3 2 1 6 5 2 6 8 3 7 0 4 9 0 ''' res = df.sort_values(by=['A', 'B'], ascending=[False, True]) print('按照A列B列的值排序:\n', res) ''' 按照A列B列的值排序: A B 4 9 0 3 7 0 1 6 5 2 6 8 0 3 2 ''' 多列排序首先按照by[]列表和ascending[]列表中的對應順序和對應邏輯進行排序,首先by列表的第一個列標籤根據其在ascending列表的對應邏輯進行排序,其次再用by列表第二個列標籤及其ascending列表的對應邏輯進行排序,以此類推。

多做幾個數據的排序

```python

代碼

data.sort_values(by=['年齡']).head(20) ```

image.png

年齡小的孩子大部分也都存活了,看來災難發生時大家讓孩子們先上了救生船

1.6.3 任務三:利用Pandas進行算術計算,計算兩個DataFrame數據相加結果

```python

自己構建兩個都為數字的DataFrame數據

代碼

frame1_a = pd.DataFrame(np.arange(9.).reshape(3, 3), columns=['a', 'b', 'c'], index=['one', 'two', 'three']) frame1_b = pd.DataFrame(np.arange(12.).reshape(4, 3), columns=['a', 'e', 'c'], index=['first', 'one', 'two', 'second']) print(frame1_a.head()) print(frame1_b.head()) ```

image.png

將frame_a和frame_b進行相加

```python

代碼

df3=frame1_a.add(frame1_b) #fill_value=0用來定義對空值使用0填充 df3.head() ```

image.png

將frame_a和frame_b進行相加,如果使用了fill_value=0用來定義對空值使用0填充(只要有一個對應位置的數據就會有值,除非相加的表中一個都找不到,比如frist b 在兩個表中都無法找到對應的值,所以只能是NaN) ```python

代碼

df3=frame1_a.add(frame1_b,fill_value=0) #fill_value=0用來定義對空值使用0填充 df3.head() ```

image.png

【提醒】兩個DataFrame相加後,會返回一個新的DataFrame,對應的行和列的值會相加,沒有對應的會變成空值NaN。

1.6.4 任務四:通過泰坦尼克號數據如何計算出在船上最大的家族有多少人?

```python

代碼

result=data['堂兄弟/妹個數'].add(data['父母與小孩個數'],fill_value=0)

max(data)

max(result)

data['堂兄弟/妹個數'].head(10)

``` 10

1.6.5 任務五:學會使用Pandas describe()函數查看數據基本統計信息

```python

代碼

frame2 = pd.DataFrame([[1.4, np.nan], [7.1, -4.5], [np.nan, np.nan], [0.75, -1.3] ], index=['a', 'b', 'c', 'd'], columns=['one', 'two']) frame2 ```

image.png

調用 describe 函數,觀察frame2的數據基本信息

```python

代碼

frame2.describe() ```

image.png

1.6.6 任務六:分別看看泰坦尼克號數據集中 票價、父母子女 這列數據的基本統計數據,你能發現什麼?

```python ''' 看看泰坦尼克號數據集中 票價 這列數據的基本統計數據 '''

代碼

data['票價'].describe() ```

image.png

【總結】本節中我們通過Pandas的一些內置函數對數據進行了初步統計查看,這個過程最重要的不是大家得掌握這些函數,而是看懂從這些函數出來的數據,構建自己的數據分析思維,這也是第一章最重要的點,希望大家學完第一章能對數據有個基本認識,瞭解自己在做什麼,為什麼這麼做,後面的章節我們將開始對數據進行清洗,進一步分析。