首先呢,該篇文會接續上一篇文章「[Python] 跌入數據分析的坑 – 談談起手式 NumPy (一)」的內容接續談論 Pandas,同時也希望自己的筆記可以幫助與我一樣正在這條不歸路上的朋友們,當然也希望可以得到一些回饋。老實說我也不知道為何總是開頭都要生一堆廢話,可是看別人文章都這樣寫,只好照做了?
目錄
前言
本篇起手式的進度來到「成為python數據分析達人的第一課(自學課程)」的第五週,七週的課程我花了三天跳到第五週似乎有點暴力,但前三週的課程基本上都在帶 Python 基礎,包括如何安裝、如何使用 IPython,雖已經稍微有些 Python 基礎,但還是全部看過,同時希望可以快點進入數據分析領域。
數據分析起手式
幾乎每個教學影片都再三強調的起手式,從第五週開始起手式多了第四行的 import pandas as pd
,同時也是今天的主角 Pandas
,至於上一篇文章中就已經加上第四行,是因為筆者學習到了第五週才開始寫文章,故既然是起手式,就一次到位吧,只要記得這四行很重要就好了,下課(WTF!?)。
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
CSV
在開始之前要先介紹一下 CSV,所謂 CSV 全名 Comma-Separated Values,簡單的說就是一個 txt 檔案,只是內文會使用 ,
來當作值與值之間的分隔號。
例如
出生年,月,日
1997,12,6
1999,3,4
1999,7,27
1996,6,18
重點:
- 列: 斷行
- 欄位: 用
,
隔開
Pandas
Pandas 一樣是 python 的 libary,pandas 很像 excel,但沒有 excel 來得直覺,同樣可以將資料呈現像試算表,在資料分析的角色中。
數據分析大多數時間都在做資料整理,基本上用 Pandas 整理資料,用 Numpy、SkLearn 等…計算分析。
Pandas 重要的兩個概念:
- Series (像是list、array,只是每欄有名稱)
- DataFrame (像是Excel的試算表表格)
Read CSV
既然要處理資料,必定要有資料來源,Pandas 提供讀入 CSV 的好方法,相較於使用 Python 原生的讀入方式更便利許多,隨後會介紹差異。
首先範例資料採取「成為python數據分析達人的第一課(自學課程)」炎龍老師 GitHub 上提供的資料。
以下程式可以讀入範例 CSV,由於此範例有 100(行) * 6(欄)
資料,相當的多,所以使用 df.head()
僅讀出前 5 個資料內容。
df = pd.read_csv("https://raw.githubusercontent.com/yenlung/Python-3-Data-Analysis-Basics/master/grades.csv")
df.head()
如果使用 Python 的原生方式,就必須使用較為繁瑣的 `open()` 方法,透過 `open()` 僅能夠處理本地檔案,而法像 Pandas 直接擷取線上的 csv 使用,便利性沒有比使用 Pandas 來得高,下圖為 `open()` 方法範例。
l=[]
with open('test.csv') as f:
lines = csv.reader(f)
for line in lines:
l.append(line)
Series
如果成功讀入資料之後,就可以使用 Pandas 來分析資料內容,Pandas 的 Series 就像是 List、Array,可以直接操作某些欄或列。
Series 的操作有兩種形式,如下,由於資料量眾多,使用 head()
作檢視。
- df.[“國文”]
- df.國文
Values
如果要針對某一個欄位來操作,也可以使用 .values
,便會將該欄位的所有資料轉成 np.Array。
df.國文.values
如果想要計算主科,可以透過以下方法。
df["主科"] = df.數學 * 1.4 + df.英文 * 1.2
變會自動幫你把每一列的數學、英文自動算好,並新增、存放到「主科」的欄位。
Mean 平均
Mean 的意思就讓我來幫各位複習一下英文,下圖為 Google 翻譯的結果。
所以可以很簡單的使用 .mean()
來計算某個欄位的平均值。
std 標準差
由於數學真的很差,借助 Wiki 的力量。
標準差(又稱標準偏差、均方差,英語:Standard Deviation,縮寫SD),數學符號σ(sigma),在機率統計中最常使用作為測量一組數值的離散程度之用。
– wiki
計算某個欄位上的標準差也相當簡單,.std()
即可搞定。
資料視覺化
還記得上一個篇文章「[Python] 跌入數據分析的坑 – 談談起手式 NumPy (一)」中有提到 plot()
方法,可以用來劃出點與點相連的圖形,同樣使用 plot()
來將國文成績一一劃出來似乎對於資料分析沒有太大的幫助,如下圖。
透過 plot()
劃出來的圖形,無法有效知道成績分布,藉此可以使用 pandas 提供的 hist()
方法來劃出直方圖。
便可以很方便得判別出國文的成績分佈。
補充:
- bins 可以控制直方圖的寬度。
DataFrame
如果 Series 是一筆資料,那 DataFrame 就是一包資料,上頭介紹 Series 是對 DataFrame 上的個別資料作處理,那關於 DataFrame 可以做些什麼操作呢?
Describe
顧名思義,用法 df.describe()
,會自動的幫你彙整該 DataFrame 的常用方法,並且輸出。
補充:
- count: 資料數
- mean: 平均值
- std: 標準差
- min: 最小值
- 25%: 25% 資料比例落在
- 50%: 50% 資料比例落在
- 75%: 75% 資料比例落在
- max: 最大值
Correlation
透過 df.corr
可以列出各個欄位之間的相關性。
也可以透過 Series 的方法列出對應
Sum
顧名思義就是加總的意思,但這部分需要注意的是,DataFrame 並不知道使用者是要行列加總還是欄位加總,所以必須指定,預設為行列加總(上下),若要欄位加總(左右),必須設定參數 sum(1)
。
補充:
- 使用 sum 時須注意加總模式(預設值:0)。
行列加總=0
欄位加總=1
Sort
你以為方法叫做 sort()
?
錯了,很龜毛的他叫做 sort_values(),顧名思義就是排序,選擇依照什麼欄位為依據,從小到大或大到小。
依據的欄位也可以是個 List,下圖以「主科」為依據由大到小排序,可以觀察到,當主科同分時,便會以「總級分」做為第二排序依據。
補充:
- by 可以是 List,參考依據會從 index[0] 開始
- ascending 可以控制排序方式
由小到大(ASC)=True
由大到小(DESC)=False
Loc
如果今天要處理的資料是特定的,例如數值小於多少、某幾欄、某幾列,皆可以透過 Loc 的定位法來處理,首先先用亂數產生新的 DataFrame(產生方法會在下一個章節說明),如下圖。
loc
方法提供了很便利的操作方式,可以直接透過 df.loc[2, "B"]
找到欄位 B 的第二行 ,藉此就可以指定該欄位的數值。
如果現在要將 df
所有資料中,大於 0 的數值設定為 1;小於等於 0 的數值設定為 0,也可以透過 loc
方法很快的達成,其中第一個參數作為判斷,返回布林值,而第二個參數表示針對哪個欄位,如下圖。
建構 DataFrame
了解基礎用法之後,便可以自己建構屬於自己的 DataFrame。
基礎語法為pd.DataFrame(np.Array, columns=List)
,其中 np.Array
為 NumPy 的 Array 上一篇文章中已經有說過,columns
必須為 List,例如 List(“ABC”),其對應的是欄位名稱,如果沒有設定則為 [1, 2, 3, …]。
下圖為,建構兩個 DataFrame,df1
、df2
,可以觀察到兩個 DataFrame 有指定 columns
與沒有指定的差異。
補充:
- DataFrame 必須由 np.Array 作為資料來源。
- DataFrame 可以指定行列名稱
index
,但要與行數相符。 - DataFrame 可以指定欄位名稱
columns
,但要與欄位數相符。
合併 DataFrame
由於這是兩個獨立的 DataFrame,如果要將 df1
與 df2
合併的話,這也不是辦不到的,可以透過 concat()
方法,透過參數 axis
,可以決定行列合併(左右)還是垂直合併(上下)。
行列合併
如果使用行列合併(左右),由於 df1
的行高於 df2
,所以合併後在 index[3] 的部分,原屬於 df2
的欄位因為沒有值,而輸出 NaN
,如下圖。
垂直合併
如同行列合併,在垂直合併後,df2
的資料被加在右下方,原因在於 df1
與 df2
使用不同的欄位名稱,df1:123
、df2:ABCD
,如下圖。
其次還有 index
的部分,預想的合併結果應該為 index[0] – index[6],卻出現重複的 index,為了解決此問題需要重新定義 index,使用 df4.index = range(7)
。
補充:
- axis 參數可以控制合併模式。
行列合併(左右)=0
垂直合併(上下)=1 - 垂直合併後 index 並不會自動疊加可以透過
dataframe.index = range(n)
來重新定義 index。
第五週作業
在這一系列的課程中,這好像是唯一的作業,僅做了第三題「第三題_錄取分數表格」,以下為程式碼。
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
course = ["國文", "英文", "數甲", "數乙", "物理", "化學", "生物", "歷史", "地理", "公民"]
score = [[86.5, 79.4, 88.2, 96.5, 86.3, 76.8, 96.1, 78.5, 82.4, 88.6]]
student = pd.DataFrame(score, index=["小明"], columns=course)
print(student)
major = ["土語系", "財政系", "金融系", "國貿系", "會計系", "法律系", "公行系", "應數系", "教育系"]
weights = [
[2, 2, 0, 1, 0, 0, 0, 1, 1, 0],
[1, 1.5, 0, 1.5, 0, 0, 0, 0, 0, 0],
[1, 1.5, 0, 2, 0, 0, 0, 0, 0, 0],
[1.5, 2, 0, 2, 0, 0, 0, 0, 0, 0],
[1.5, 2, 0, 2, 0, 0, 0, 1, 1, 0],
[1, 2, 0, 1, 0, 0, 0, 1, 0, 1],
[1, 1.5, 0, 1.25, 0, 0, 0, 0, 0, 1.25],
[1, 1, 1.5, 0, 1, 1, 0, 0, 0, 0],
[1.5, 2, 0, 1.25, 0, 0, 0, 1, 1, 0]
]
weights_df = pd.DataFrame(np.array(weights), index=major, columns=course)
print(weights_df)
weights_df["加權分數"] = 0
for i in course:
weights_df["加權分數"] = weights_df["加權分數"] + weights_df[i] * student.loc["小明", i]
print(weights_df)
thanks for sharing 🙂