這篇文章主要介紹了關於Pandas實現資料類型轉換的一些技巧,有著一定的參考價值,現在分享給大家,有需要的朋友可以參考一下
前言
Pandas是Python當中重要的資料分析工具,利用Pandas進行資料分析時,確保使用正確的資料類型是非常重要的,否則可能會導致一些不可預知的錯誤發生。
Pandas 的資料類型:資料類型本質上是程式設計語言用來理解如何儲存和操作資料的內部結構。例如,一個程式需要理解你可以將兩個數字加起來,比如 5 + 10 得到 15。或者,如果是兩個字串,比如「cat」和「hat」,你可以將它們串連(加)起來得到「cathat」。尚學堂•百戰程式員陳老師指出有關 Pandas 資料類型的一個可能令人困惑的地方是,Pandas、Python 和 numpy 的資料類型之間有一些重疊。
大多數情況下,你不必擔心是否應該明確地將熊貓類型強制轉換為對應的 NumPy 類型。一般來說使用 Pandas 的預設 int64 和 float64 就可以。我列出此表的唯一原因是,有時你可能會在程式碼間或自己的分析過程中看到 Numpy 的類型。
資料類型是在你遇到錯誤或意外結果之前並不會關心的事情之一。不過當你將新資料載入到 Pandas 進行進一步分析時,這也是你應該檢查的第一件事情。
筆者使用Pandas已經有一段時間了,但是還是會在一些小問題上犯錯誤,追根溯摘要搜索在對資料進行操作時某些特徵列並不是Pandas所能處理的類型。因此本文將討論一些小技巧如何將Python的基礎資料型別 (Elementary Data Type)轉化為Pandas所能處理的資料類型。
Pandas、Numpy、Python各自支援的資料類型
從上述表格中可以看出Pandas支援的資料類型最為豐富,在某種情形下Numpy的資料類型可以和Pandas的資料類型相互轉化,畢竟Pandas庫是在Numpy的基礎之上開發的的。
引入實際資料進行分析
資料類型是你平常可能不太關心,直到得到了錯誤的結果才映像深刻的東西,因此在這裡引入一個實際資料分析的例子來加深理解。
import numpy as npimport pandas as pddata = pd.read_csv('data.csv', encoding='gbk') #因為資料中含有中文資料data
資料載入完畢,如果現在想要在該資料上進行一些操作,比如把資料列2016、2017對應項相加。
data['2016'] + data['2017'] #想當然的做法
從結果來看並沒有像想象中那樣數值對應相加,這是因為在Pandas中object類型相加等價於Python中的字串相加。
data.info() #在對資料進行處理之前應該先查看載入資料的相關資訊
在看到載入資料的相關資訊後可以發現如下幾個問題:
客戶編碼的資料類型是int64而不是object類型
2016、2017列的資料類型是object而不是數實值型別(int64、float64)
增長率、所屬組的資料類型應該為數實值型別而不是object類型
year、month、day的資料類型應該為datetime64類型而不是object類型
Pandas中進行資料類型轉換有三種基本方法:
使用astype()函數進行類型轉換
對資料列進行資料類型轉換最簡單的方法就是使用astype()函數
data['客戶編碼'].astype('object')data['客戶編碼'] = data['客戶編碼'].astype('object') #對未經處理資料進行轉換並覆蓋未經處理資料列
上面的結果看起來很不錯,接下來給出幾個astype()函數作用於列資料但失效的例子
data['2017'].astype('float')
data['所屬組'].astype('int')
從上面兩個例子可以看出,當待轉換列中含有不能轉換的特殊值時(例子中¥,ErrorValue等)astype()函數將失效。有些時候astype()函數執行成功了也並不一定代表著執行結果符合預期(神坑!)
data['狀態'].astype('bool')
乍一看,結果看起來不錯,但仔細觀察後,會發現一個大問題。那就是所有的值都被替換為True了,但是該列中包含好幾個N標誌,所以astype()函數在該列也是失效的。
總結一下astype()函數有效情形:
如果資料中含有缺失值、特殊字元astype()函數可能失效。
使用自訂函數進行資料類型轉換
該方法特別適用於待轉換資料列的資料較為複雜的情形,可以通過構建一個函數應用於資料列的每一個資料,並將其轉換為適合的資料類型。
對於上述資料中的貨幣,需要將它轉換為float類型,因此可以寫一個轉換函式:
def convert_currency(value): """ 轉換字串數字為float類型 - 移除 ¥ , - 轉化為float類型 """ new_value = value.replace(',', '').replace('¥', '') return np.float(new_value)
現在可以使用Pandas的apply函數通過covert_currency函數應用於2016列中的所有資料中。
data['2016'].apply(convert_currency)
該列所有的資料都轉換成對應的數實值型別了,因此可以對該列資料進行常見的數學操作了。如果利用lambda運算式改寫一下代碼,可能會比較簡潔但是對新手不太友好。
data['2016'].apply(lambda x: x.replace('¥', '').replace(',', '')).astype('float')
當函數需要重複應用於多個列時,個人推薦使用第一種方法,先定義函數還有一個好處就是可以搭配read_csv()函數使用(後面介紹)。
#2016、2017列完整的轉碼data['2016'] = data['2016'].apply(convert_currency)data['2017'] = data['2017'].apply(convert_currency)
同樣的方法運用於增長率,首先構建自訂函數
def convert_percent(value): """ 轉換字串百分數為float類型小數 - 移除 % - 除以100轉換為小數 """ new_value = value.replace('%', '') return float(new_value) / 100
使用Pandas的apply函數通過covert_percent函數應用於增長率列中的所有資料中。
data['增長率'].apply(convert_percent)
使用lambda運算式:
data['增長率'].apply(lambda x: x.replace('%', '')).astype('float') / 100
結果都相同:
為了轉換狀態列,可以使用Numpy中的where函數,把值為Y的映射成True,其他值全部映射成False。
data['狀態'] = np.where(data['狀態'] == 'Y', True, False)
同樣的你也可以使用自訂函數或者使用lambda運算式,這些方法都可以完美的解決這個問題,這裡只是多提供一種思路。
利用Pandas的一些輔助函數進行類型轉換
Pandas的astype()函數和複雜的自定函數之間有一個中間段,那就是Pandas的一些輔助函數。這些輔助函數對於某些特定資料類型的轉換非常有用(如to_numeric()、to_datetime())。所屬組資料列中包含一個非數值,用astype()轉換出現了錯誤,然而用to_numeric()函數處理就優雅很多。
pd.to_numeric(data['所屬組'], errors='coerce').fillna(0)
可以看到,非數值被替換成0.0了,當然這個填儲值是可以選擇的,具體文檔見
pandas.to_numeric - pandas 0.22.0 documentation
Pandas中的to_datetime()函數可以把單獨的year、month、day三列合并成一個單獨的時間戳記。
pd.to_datetime(data[['day', 'month', 'year']])
完成資料列的替換
data['new_date'] = pd.to_datetime(data[['day', 'month', 'year']]) #新產生的一列資料data['所屬組'] = pd.to_numeric(data['所屬組'], errors='coerce').fillna(0)
到這裡所有的資料列都轉換完畢,最終的資料顯示:
在讀取資料時就對資料類型進行轉換,一步到位
data2 = pd.read_csv("data.csv", converters={ '客戶編碼': str, '2016': convert_currency, '2017': convert_currency, '增長率': convert_percent, '所屬組': lambda x: pd.to_numeric(x, errors='coerce'), '狀態': lambda x: np.where(x == "Y", True, False) }, encoding='gbk')
在這裡也體現了使用自訂函數比lambda運算式要方便很多。(大部分情況下lambda還是很簡潔的,筆者自己也很喜歡使用)
總結
對資料集進行操作的第一步是確保設定正確的資料類型,然後才能進行資料的分析、可視化等操作,Pandas提供了很多非常方便的函數,有了這些函數那麼對資料進行分析將會是很方便的。