Open Data:
在前一篇文章中我們介紹了如何將資料進行分組以及利用特定條件篩選所需資料,這些技術都是檢視資料的範疇,接下來我們將進入資料清理的環節,畢竟在正常情況下,我們所得到的資料並非都非常完美,可能會因為收集方便或是人為疏失造成資料的儲存形式較不利於分析的情況,這時候我們就需要將資料先行整理成容易分析的結構或是型別,降低分析的時間成本,這也是資料清理的價值。
- 使用資料表
Notebook Content:
這次我們會使用google play store(‘googleplaystore.csv’)的公開資料,其中紀錄了google play平台商店中所有app的分類、評分、下載量、名稱、大小⋯⋯等相關資料,假設我們是一間app開發公司的分析人員,我們想研究目前市場中哪些分類的評分以及下載量是比較高的。
因為是使用新資料,所以我們先利用 pd.read_csv() 讀取並顯示前五筆資料:
import pandas as pd google = pd.read_csv('googleplaystore.csv') print(google.head());
從下方結果可以發現,google的資料跟先前使用的app資料有些不同,像是欄位名稱的寫法,還有紀錄的內容分類也有些許的不同:
App Category Rating 0 Photo Editor & Candy Camera & Grid & ScrapBook ART_AND_DESIGN 4.1 1 Coloring book moana ART_AND_DESIGN 3.9 2 U Launcher Lite – FREE Live Cool Themes, Hide ... ART_AND_DESIGN 4.7 3 Sketch - Draw & Paint ART_AND_DESIGN 4.5 4 Pixel Draw - Number Art Coloring Book ART_AND_DESIGN 4.3 Reviews Size Installs Type Price Content Rating 0 159 19M 10,000+ Free 0 Everyone 1 967 14M 500,000+ Free 0 Everyone 2 87510 8.7M 5,000,000+ Free 0 Everyone 3 215644 25M 50,000,000+ Free 0 Teen 4 967 2.8M 100,000+ Free 0 Everyone Genres Last Updated Current Ver 0 Art & Design January 7, 2018 1.0.0 1 Art & Design;Pretend Play January 15, 2018 2.0.0 2 Art & Design August 1, 2018 1.2.4 3 Art & Design June 8, 2018 Varies with device 4 Art & Design;Creativity June 20, 2018 1.1 Android Ver 0 4.0.3 and up 1 4.0.3 and up 2 4.0.3 and up 3 4.2 and up 4 4.4 and up
df.rename() 修改欄位命名 (官方document):
首先我們先從欄位名稱開始,在欄位名稱的使用上比較常見的寫法有兩種,分別為 Camel Case 與 Snake Case 兩種,這兩種寫法在程式語言的命名規則中很常見。這邊我們只針對 Snake Case 做說明,想了解 Camel Case 可以點擊上面的連結,Snake Case 的規則是:
- 全部字母為小寫
- 如果有兩個以上的字母,使用「 _ 」符號做串連
- Ex. snake_case
- 特性:辨識度高,且選取操作的效率好
而在進行資料處理時,因為很常使用到欄位名稱去定位資料,所以欄位名稱的寫法會有很大程度的影響我們操作上的效率,舉例來說像是「snake case」與「snake_case」兩者雖然只有空格與底線的差別,但當我們要選取複製這兩個欄位名稱時,後者的寫法我們可以透過雙擊直接選取,但前者需要使用游標匡選,方便性就低了些。
在進行資料處理上面,我會比較推薦大家使用 Snake Case ,因為它相較於 Camel Case 有較高的辨識度,不過這方面比較見仁見智,並沒有特別強求,主要自己習慣即可。接下來我們要試著將資料表 google 的欄位名稱改成 Snake Case 模式:
mapping = { 'Content Rating':'content_rating', 'Last Updated':'last_updated', 'Current Ver':'current_ver', 'Android Ver':'android_ver', } google = google.rename(mapping,axis=1); print(google.columns)
首先我們先利用 dict() 定義了我們要指定哪些欄位以及要將這些欄位名稱改成什麼,字典中的key值就是挑選的欄位,value值則是欲修改成的名稱,完成後我們將這個字典引入 df.rename()方法,並設定參數 axis 為 1 ,axis=1 代表針對「欄位(columns)」的操作,這個方法也可以修改「索引(index)」的名稱,如果是針對索引的操作,只要設定 axis=0 即可。
這邊我們利用 df.columns 屬性查看欄位修改後的結果,可以看到我們所選的四個欄位名稱已經變成 Snake Case的寫法了:
Index(['App', 'Category', 'Rating', 'Reviews', 'Size', 'Installs', 'Type', 'Price', 'content_rating', 'Genres', 'last_updated', 'current_ver', 'android_ver'], dtype='object')
df.columns.str.method 直接針對欄位進行字串操作 (官方document):
除了利用 df.rename() 方法之外,也可以直接針對 df.columns 屬性進行字串操作,比如說,剛才我們先將部分有多個單字的欄位改成 Snake Case ,但其他的欄位我們也希望皆為小寫,所以我們直接針對 df.columns 進行操作:
google.columns = google.columns.str.lower() print(google.columns)
這邊我們使用了一個pandas套件的資料處理技術叫做「vectorized string methods」,這個技術可以讓我們不需要使用迴圈,一次將 Series 中的所有字串進行相同的字串操作,只要在字串操作方法前加上 .str 即可,此方法我們會在之後的文章中提到,然而這個方法也可以運用在 df.columns,所以我們利用.str.lower() 將所有欄位名稱一次改成小寫字母,如下面的結果:
Index(['app', 'category', 'rating', 'reviews', 'size', 'installs', 'type', 'price', 'content_rating', 'genres', 'last_updated', 'current_ver', 'android_ver'], dtype='object')
在處理完欄位名稱之後,我們要接著縮減資料的大小,因為我們在分析的時候未必會使用到所有的欄位或是每一筆資料,如果是跟研究目標沒有相關的資料,我們會將該欄位進行刪除,以增加資料處理的速度。
df.drop() 資料/欄位刪除 (官方document):
若要進行整行或整欄的資料刪除,只需在 df.drop() 方法中引入索引/欄位名稱,並設定參數 axis 為 1 或 0 即可,不過這邊要注意,此方法並不像 list.pop() 會自動存取刪減後的物件,是需要重新賦值的,雖然有些麻煩,但好處是我們可以先看看資料刪減後的樣子是否跟我們預想的一樣,如果和預想相同,再進行賦值,以免誤刪重要的資料。
像針對 google 資料,我們並不會使用到各個軟體的版本更新資料,所以我們將欄位last_updated進行刪除:
google = google.drop('last_updated',axis=1) #因為是刪除「欄位」,所以設定axis=1 print(google.columns)
Index(['App', 'Category', 'Rating', 'Reviews', 'Size', 'Installs', 'Type', 'Price', 'content_rating', 'Genres', 'current_ver', 'android_ver'], dtype='object')
從上面的 df.columns 輸出結果可以看到,last_updated 已經成功被我們刪除。
然而 df.drop() 方法不只可以刪除欄位,也可以配合「條件篩選」刪除不必要的數筆資料,例如,因為我們是發展免費軟體,所以我們要刪除所有付費軟體的資料,首先我們先篩選「軟體費用不為零」的所有資料:
首先我們先看一下欄位price的資料狀況
print(google['price'].describe())
count 10841 #總共有10841筆資料 unique 93 top 0 freq 10040 Name: price, dtype: object
接著我們篩選條件「價格欄位不為零的資料」作為 mask 並提取所有符合條件資料,然後取得這些資料的索引值,作為 df.drop() 的參數,然後因為是刪除索引,所以設定 axis=0 :
mask = google['price']!='0' #建立資料篩選遮罩 pay_app = google.loc[mask] #利用遮罩篩選資料 google = google.drop(pay_app.index,axis=0) #將刪除後的資料表重新賦值 print(pay_app['price'].describe()) #確認有多少筆資料為付費軟體
count 801 #有801筆付費資料 unique 92 top $0.99 freq 148 Name: price, dtype: object
在進行資料刪除後,我們再次確認價格欄位的資料數:
print(google['price'].describe())
結果顯示,少了801筆資料,跟上面的付費軟體資料數吻合,代表付費軟體資料成功被刪除:
count 10040 #總共有10040筆資料 unique 93 top 0 freq 10040 Name: price, dtype: object
df.dtypes / df.astype() / Series.astype() 改變資料型別 (官方document):
在進行資料處理時常會碰到欄位型別的問題,在Pandas中常見的資料型別主要分為 int(整數), float64(浮點數) , object(字串) 三種,我們可以利用 df.dtypes 顯示所有欄位的資料型別:
print(google.dtypes)
app object category object rating float64 reviews object size object installs object type object price object content_rating object genres object current_ver object android_ver object dtype: object
在這些型別中,整數與浮點數欄位都可以進行所有數值的計算,像是當我們使用 df.describe() 方法時,這兩種數值欄位會自動計算平均數、最大值、最小值、標準差……等統計數值;但字串欄位因為沒有數值意義,無法進行運算,所以只會回傳出現最多次的字串、出現次數以及欄位中有幾種不同的值,如下所示:
google['rating'].describe()
count 8719.000000 mean 4.186203 std 0.512338 min 1.000000 25% 4.000000 50% 4.300000 75% 4.500000 max 5.000000 Name: rating, dtype: float64
從上面的結果中可以看到,pandas回傳了「下載率」欄位的各項統計數值。
google['category'].describe()
count 10040 unique 33 top FAMILY freq 1781 Name: category, dtype: object
跟浮點數與整數型別不同,object 型別欄位利用 Series.describe() 的回傳結果只會有「資料數」、「獨立值數量」、「出現次數最高的值」、「出現率最高的值的出現次數」。
然而,有些時候我們很常會遇到一種狀況:資料內容為數值內容,但因為存取或是記錄時的問題,導致欄位型別為非數值型別,這個問題可能會導致我們在進行資料處理時遇到一些因型別而無法計算的情況發生,為了避免這件事,我們需要一個方法能夠讓我們進行資料型別的轉換,那就是 df.astype() 。
其實這個方法跟python原生的函式 type() 使用方式一樣,只要將欲修改的欄位 Series 使用 astype() 並設定要修改為什麼型別即可,操作如下:
我們現在想將各個App的總安裝次數轉換為整數型別,首先我們已經先將欄位欲處理為數字的字串欄位 installs_int 並顯示前五筆資料數值:
print(google['installs_int'].head())
0 10000 1 500000 2 5000000 3 50000000 4 100000 Name: installs_int, dtype: object
從結果可以發現,雖然內容看起來是數值沒有問題,但仔細看下方的 dtype ,這個欄位的型別其實是字串而非整數,所以我們要使用 Series.astype() 將這個欄位的型別轉換為 int (整數):
google['installs_int'] = google['installs_int'].astype(int) print(google['installs_int'].head())
0 10000 1 500000 2 5000000 3 50000000 4 100000 Name: installs_int, dtype: int64
當我們完成型別轉換之後,再次顯示前五筆資料並檢查 dtype 可以看到,欄位型別已經成功轉換為整數型別,這樣一來就可以進行下一步的計算了!
Written by
Glove Yen
一個不務正業的企管人,喜歡有創造性的事物,從管理到設計到程式,目前正在鑽研資料科學以及網頁前端開發,不知從什麼時候開始已經習慣了每天coding的日子。
—轉自好文作者Glove Yen_Data Science_Python資料處理套件part4 – Pandas 整理資料欄位與型別
如果你喜歡他的文章、Python資料分析有興趣,歡迎回到他的Blog: glove-coding看更多:)
或接續觀看Pandas 第6講:Python資料處理套件Pandas 資料字串處理
📒 Python Pandas 系列文章:
Pandas 第1講:Python資料處理套件Pandas簡介
Pandas 第2講:Python資料處理套件Pandas資料儲存物件
Pandas 第3講:Python資料處理套件Pandas檢視與定位資料
Pandas 第4講:Python資料處理套件Pandas條件篩選資料
Pandas 第5講:Python資料處理套件Pandas整理資料欄位與型別(本文)
Pandas 第6講:Python資料處理套件Pandas 資料字串處理
Pandas 第7講:Python資料處理套件Pandas數值處理與基礎統計量
快樂學程式在Udemy 也推出了以Pandas 套件進行資料處理的實戰課程,這次是將Python已視覺化的方式
對資料進行解析,只要一個假日拉高你的職場競爭力!快來這裡一起快樂學程式!
如果你的入門還在單打獨鬥,歡迎來到快樂學程式找到志同道合的夥伴,你的自學之路不孤單。