首先導入相關模塊並加載數據集到 Python 環境中:python
import pandas as pd
import numpy as np
data = pd.read_csv("train.csv", index_col="Loan_ID")git
若是須要以其它列數據值爲條件過濾某一列的數據,您會怎麼處理?例如創建一個列表,列表中所有爲未能畢業但曾得到貸款的女性。這裏可使用布爾索引,代碼以下:github
Apply 函數是處理數據和創建新變量的經常使用函數之一。在向數據框的每一行或每一列傳遞指定函數後,Apply 函數會返回相應的值。這個由 Apply 傳入的函數能夠是系統默認的或者用戶自定義的。例如,在下面的例子中它能夠用於查找每一行和每一列中的缺失值。算法
#Create a new function:
def num_missing(x):
return sum(x.isnull())數組
#Applying per column:
print "Missing values per column:"
print data.apply(num_missing, axis=0) #axis=0 defines that function is to be applied on each columnapp
#Applying per row:
print "nMissing values per row:"
print data.apply(num_missing, axis=1).head() #axis=1 defines that function is to be applied on each row框架
這樣咱們就獲得了所需的結果。ide
注:因爲輸出結果包含多行數據,第二個輸出函數使用了 head() 函數以限定輸出數據長度。在不限定輸入參數時 head() 函數默認輸出 5 行數據。函數
fillna() 函數可一次性完成填補功能。它能夠利用所在列的均值/衆數/中位數來替換該列的缺失數據。下面利用「Gender」、「Married」、和「Self_Employed」列中各自的衆數值填補對應列的缺失數據。測試
#First we import a function to determine the mode
from scipy.stats import mode
mode(data['Gender'])
輸出結果爲:ModeResult(mode=array([‘Male’], dtype=object), count=array([489]))
輸出結果返回了衆數值和對應次數。須要記住的是因爲可能存在多個高頻出現的重複數據,所以衆數能夠是一個數組。一般默認使用第一個衆數值:
mode(data['Gender']).mode[0]
如今能夠進行缺失數據值填補並利用#2方法進行檢查。
#Impute the values:
data['Gender'].fillna(mode(data['Gender']).mode[0], inplace=True)
data['Married'].fillna(mode(data['Married']).mode[0], inplace=True)
data['Self_Employed'].fillna(mode(data['Self_Employed']).mode[0], inplace=True)
#Now check the #missing values again to confirm:
print data.apply(num_missing, axis=0)
至此,能夠肯定缺失值已經被填補。請注意,上述方法是最基本的填補方法。包括缺失值建模,用分組平均數(均值/衆數/中位數)填補在內的其餘複雜方法將在接下來的文章中進行介紹。
Pandas 可創建 MS Excel 類型的數據透視表。例如在下文的代碼段裏,關鍵列「LoanAmount」 存在缺失值。咱們能夠根據「Gender」,「Married」和「Self_Employed」分組後的平均金額來替換。 「LoanAmount」的各組均值可由以下方法肯定:
#Determine pivot table
impute_grps = data.pivot_table(values=["LoanAmount"], index=["Gender","Married","Self_Employed"], aggfunc=np.mean)
print impute_grps
若是您注意觀察#3計算的輸出內容,會發現它有一個奇怪的性質。即每一個索引均由三個數值的組合構成,稱爲複合索引。它有助於運算操做的快速進行。
從#3的例子繼續開始,已知每一個分組數據值但還未進行數據填補。具體的填補方式可結合此前學到的多個技巧來完成。
#iterate only through rows with missing LoanAmount
for i,row in data.loc[data['LoanAmount'].isnull(),:].iterrows():
ind = tuple([row['Gender'],row['Married'],row['Self_Employed']])
data.loc[i,'LoanAmount'] = impute_grps.loc[ind].values[0]
#Now check the #missing values again to confirm:
print data.apply(num_missing, axis=0)
Note:
注:
1. 多值索引須要在 loc 語句中使用用於定義索引分組的元組結構。該元組會在函數中使用。
2. 應使用後綴 .values[0] 以免潛在的錯誤。由於默認狀況下複合索引返回的 Series 元素索引順序與所在的數據框架(dataframe)不一致。在此條件下直接賦值會產生錯誤。
該函數用於獲取數據的初始印象(直觀視圖),從而驗證一些基本假設。例如在本例中,「Credit_History」被認爲會顯著影響貸款狀態。這個假設能夠經過以下代碼生成的交叉表進行驗證:
pd.crosstab(data["Credit_History"],data["Loan_Status"],margins=True)
以上這些都是絕對值。但百分比形式能得到更爲直觀的數據結果。使用 apply 函數可實現該功能:
def percConvert(ser):
return ser/float(ser[-1])
pd.crosstab(data["Credit_History"],data["Loan_Status"],margins=True).apply(percConvert, axis=1)
如今能夠證實:與僅佔9%的無信用記錄人羣相比,佔比爲80%的有信用記錄人羣得到貸款的概率會更高。
但這並非所有的數據結果,其中還包含了一個有趣的內容。既然已知有信用記錄很是重要,若是利用信用記錄狀況進行貸款預測會如何?其中,預測有信用記錄的人的得到貸款狀態爲 Y,不然爲 N。使人吃驚的是在614次測試中,共正確預測了 82+378=460 次,正確率高達75%!
若是您正好奇爲何咱們須要統計模型,我一點兒也不會責怪您。可是請相信,提升預測精度是一項很是具備挑戰性的任務,哪怕僅僅是在上述預測結果的基礎上提升0.001%的預測精度也是如此。您會接受這個挑戰嗎?
注:75% 是對本文的訓練數據集而言。測試數據集的結果將會有所不一樣,但也很是接近。一樣地,但願經過這個例子能讓你們明白爲何僅僅提升0.05%的預測精度就可在Kaggle排行榜中排名躍升500位。
當有來自不一樣數據源的信息須要收集整理時,合併數據框就變成了一項必不可少的基本操做。考慮一個假設的狀況,即不一樣類型的房產有不一樣的均價(單位:INR / 平方米)。定義數據框以下:
prop_rates = pd.DataFrame([1000, 5000, 12000], index=['Rural','Semiurban','Urban'],columns=['rates'])
prop_rates
如今可將上述信息與原始數據框合併以下:
data_merged = data.merge(right=prop_rates, how='inner',left_on='Property_Area',right_index=True, sort=False)
data_merged.pivot_table(values='Credit_History',index=['Property_Area','rates'], aggfunc=len)
上述透視表驗證了合併操做成功。須要注意的是因爲上述代碼僅對數據值進行簡單計算,所以‘values’參數在本例中是一個獨立內容,與上下文無關。
Pandas 容許基於多列數據進行簡單排列。具體實現以下:
data_sorted = data.sort_values(['ApplicantIncome','CoapplicantIncome'], ascending=False)
data_sorted[['ApplicantIncome','CoapplicantIncome']].head(10)
有時將數值數據聚合在一塊兒會更有意義。例如,若是咱們要根據一天中的某個時間段(單位:分鐘)創建交通流量模型模型(以路上的汽車爲統計目標)。與具體的分鐘數相比,對於交通流量預測而言一天中的具體時間段則更爲重要,如「早上」、 「下午」、「傍晚」、「夜晚」、「深夜(Late Night)」。以這種方式創建交通流量模型則更爲直觀且避免了過擬合狀況的發生。
下面的例子中定義了一個簡單的可重用函數,該函數能夠很是輕鬆地實現任意變量的分箱功能。
#Binning:
def binning(col, cut_points, labels=None):
#Define min and max values:
minval = col.min()
maxval = col.max()
#create list by adding min and max to cut_points
break_points = [minval] + cut_points + [maxval]
#if no labels provided, use default labels 0 ... (n-1)
if not labels:
labels = range(len(cut_points)+1)
#Binning using cut function of pandas
colBin = pd.cut(col,bins=break_points,labels=labels,include_lowest=True)
return colBin
#Binning age:
cut_points = [90,140,190]
labels = ["low","medium","high","very high"]
data["LoanAmount_Bin"] = binning(data["LoanAmount"], cut_points, labels)
print pd.value_counts(data["LoanAmount_Bin"], sort=False)
一般咱們會遇到須要對名義變量進行分類的狀況。可能的緣由以下:
1. 一些算法(如邏輯迴歸算法)要求輸入參數所有爲數字。所以名義變量多須要編碼爲0, 1….(n-1)。
2. 有時同一種分類能夠表示爲兩種形式。如溫度可能被記錄爲「高(High)」、「中(Medium)」、「低(Low)」、「高(H)」、「低(low)」。在這裏,「高(High)」和「高(H)」都表示同一種分類。相似地在「低(Low)」和「低(low)」的表示方法中僅存在大小寫的區別。但 python 將會將它們視爲不一樣的溫度水平。
3.一些分類的出現頻率可能較低,所以將這些分類歸爲一類不失爲一個好主意。
下面的例子中定義了一個通用函數,該函數使用字典做爲輸入,並利用 Pandas 模塊的‘replace’函數對字典值進行編碼。
#Define a generic function using Pandas replace function
def coding(col, codeDict):
colCoded = pd.Series(col, copy=True)
for key, value in codeDict.items():
colCoded.replace(key, value, inplace=True)
return colCoded
#Coding LoanStatus as Y=1, N=0:
print 'Before Coding:'
print pd.value_counts(data["Loan_Status"])
data["Loan_Status_Coded"] = coding(data["Loan_Status"], {'N':0,'Y':1})
print 'nAfter Coding:'
print pd.value_counts(data["Loan_Status_Coded"])
這個操做不常用。但您也不但願被這個問題卡住,對吧?有時須要利用 for 循環對全部行數據進行迭代。例如一個常見的問題便是 Python 中變量的不當處理。一般發生在以下狀況:
1.帶有數字的名義變量被認爲是數值數據。
2.因爲數據錯誤,帶有字符的數值變量輸入行數據中時被認爲是分類變量。
所以手動定義列數據類型會是一個不錯的主意。若是檢查全部列數據的數據類型:
#Check current type:
data.dtypes
會看到名義變量 Credit_History 被顯示爲 float 類型。解決這種問題的一個好方法便是建立一個包含列名和對應類型的 csv 文件。這樣就能夠定義一個通用函數來讀取文件,並指定列數據的類型。例如在下面的例子裏創建了一個 csv 文件「datatypes.csv」。
#Load the file:
colTypes = pd.read_csv('datatypes.csv')
print colTypes
加載數據後能夠對每一行進行迭代,並利用‘type’列中的數據內容肯定‘feature’列中對應變量名的數據類型。
#Iterate through each row and assign variable type.
#Note: astype is used to assign types
for i, row in colTypes.iterrows(): #i: dataframe index; row: each row in series format
if row['type']=="categorical":
data[row['feature']]=data[row['feature']].astype(np.object)
elif row['type']=="continuous":
data[row['feature']]=data[row['feature']].astype(np.float)
print data.dtypes
如今 credit history 列被定義爲了 ‘object’ 類型,該類型即爲 Pandas 模塊中用於表示名義變量的數據類型。