數據加載
首先在Kaggle上找到對應的競賽頁面,報名參賽下載數據,可以得到了一個train.csv和test.csv文件。
當然,如果你的電腦上已經安裝了kaggle的包,當然也可以使用命令行直接下載:
kaggle competitions download -c titanic
接着載入數據,可以選擇使用相對路徑或絕對路徑,這里將使用絕對路徑,將表頭修改成中文,索引改為乘客的ID,便於觀察。
'''
----- kaggle_titanic
|----- train.csv
|----- test.csv
----- data_analysis.ipynb
'''
df = pd.read_csv('kaggle_titanic/train.csv', names = ['乘客ID', '是否幸存', '倉位等級', '姓名', '性別', '年齡', \
'兄弟姐妹個數', '父母子女個數', '船票信息', '票價', '客艙', '登船港口'], index_col='乘客ID', header = 0)
'''
常用params:
- chunksize: number,表示在逐塊提取過程中,每一塊的行數。
- names: list[],和列數相同,表頭修改后的別名
- index_col: 默認為False/number,表示是否重新設置新的索引index
- header: 當選擇默認值或header=0時,將首行設為列名。如果為1的話,展示的表格就從第二行開始
'''
其中,chunksize是在對數據進行逐塊提取時使用的參數。之所以進行逐塊提取,是因為當你從一個有40億行數據的csv文件中抽取出滿足條件的某些行的數據,如果直接使用pandas的read_csv()方法去讀取這個csv文件,那服務器的內存是會吃不消的,所以就非常有必要使用chunksize去分塊處理。而經過chunksize后將得到一個可迭代的返回結果:
chunker = pd.read_csv(path, chunksize=100)
type(chunker) # <class 'pandas.io.parsers.TextFileReader'>
for chunk in chunker
print(chunk) # 發現每一個chunk都有100行
當然,你也可以使用其他方法去替換表頭,比如說
# 方法一: 直接修改columns
df.columns = ['乘客ID', '是否幸存', '倉位等級', '姓名', '性別', '年齡', \
'兄弟姐妹個數', '父母子女個數', '船票信息', '票價', '客艙', '登船港口']
# 方法二: 重命名columns
df.rename(columns={'乘客ID': 'userID', ....}, inplace=True) # 注意inplace=True時將直接修改df
# 最后,還是要設置一個新的索引
df = df.set_index(keys=['乘客ID', '是否幸存' ])
'''
np.set_index():
函數原型:DataFrame.set_index(keys, drop=True, append=False, inplace=False, verify_integrity=False)
參數解釋:
- keys:列標簽或列標簽/數組列表,需要設置為索引的列
- drop:默認為True,刪除用作新索引的列
- append:默認為False,是否將列附加到現有索引
- inplace:默認為False,適當修改DataFrame(不要創建新對象)
- verify_integrity:默認為false,檢查新索引的副本。否則,請將檢查推遲到必要時進行。將其設置為false將提高該方法的性能。
'''
接着你可以使用一些操作簡單的看看數據。
df.info()
df.head(10) # df.tail(10)
df.isnull().head() # 判斷數據是否為空,為空的地方返回True,其余地方返回False
df.to_csv(filename)
對於一個數據,你還可以從每列的數據類型來觀察。當然,對於泰坦尼克號這一數據集而言,還可以進一步觀察性別與生存率、倉位等級(社會等級)與生存率、家屬數與生存率、年齡與生存率等數據之間的關系。
Pandas的相關知識
Pandas中有兩個數據類型DataFrame和Series。
Series是一種類似於一維數組的對象。它由一組數據(各種Numpy數據類型)以及一組與之相關的數據標簽(即索引)組成,它只有行索引。
DataFrame是一個表格型的數據結構,它含有一組有序的列,每列可以是不同的值類型(數值、字符串、布爾型值)。DataFrame既有行索引也有列索引,它可以被看做由Series組成的字典(共同用一個索引)。
我們比較常用的是DataFrame,通過簡單的操作查看DataFrame的結構:
df.columns
df['xxx'] # 可以查看表頭為xxx這列的所有項
del df['xxx'] # 列刪除
當然,你依舊可以考慮用其他方法刪除多余的列:
df.drop(['性別', '票價'],axis=1, inplace=True) # 刪除多列
# inplace 是起了一個保存作用,如果沒有它,就只是隱藏了列元而已
接着可以做一些條件篩選,比如找到年紀大於50歲的乘客,或者是找到年紀大於40和小於20的乘客,涉及到一些交並的操作:
midage = df[(df["年齡"] > 50) | (df["年齡"] < 20)] # 並集
midage = df[(df["年齡"] > 50) & (df["年齡"] < 20)] # 交集
當你想取特定行特定列的元素時,你或許需要將之前設定的“乘客id”索引給刪去,這樣才能完成特定行的獲取。
midage = midage.reset_index(drop=True)
'''
reset_index():
函數原型:DataFrame.reset_index(level=None, drop=False, inplace=False, col_level=0, col_fill='')
參數解釋:
- level:int、str、tuple或list,默認無,僅從索引中刪除給定級別。默認情況下移除所有級別。
- drop:drop為False則索引列會被還原為普通列,否則會丟失
- inplace:默認為false,適當修改DataFrame(不要創建新對象)
- col_level:int或str,默認值為0,如果列有多個級別,則確定將標簽插入到哪個級別。默認情況下,它將插入到第一級。
- col_fill:對象,默認‘’,如果列有多個級別,則確定其他級別的命名方式。如果沒有,則重復索引名
'''
然后你就可以進行“定位”取數的操作了:
midage.loc[[100, 105, 108], ['Pclass', 'Name', 'Sex']]
midage.iloc[[100, 105, 108], [2, 3, 4]] # iloc不能直接通過列名獲取數值,而是要寫出第幾列
另外,可進行特定行列取數的函數還有iloc()
,兩者之間的差異可參考博客:https://blog.csdn.net/Leon_Kbl/article/details/97492966,寫得非常清楚。
我們有的時候會對兩個DataFrame相加,這時候會返回一個新的DataFrame,對應的行和列的值會想加,沒有對應的就會變成空值。比如說兩個DataFrame的(1, 1)位置上,都有值1,那么兩者想加的結果就是2。反之一個有一個無,則得到的結果就是NaN。
數據分析探索
很多網站的表格都會做一個升序降序的功能,在數據分析的時候我們也會有這類的需求:
df.sort_value(by=['xx', 'xx'], ascending=True)
'''
params:
- by: 選擇待排序的列,可以是單個也可以多個
- ascending: True/False,True是升序
'''
你還可以選擇對行、列索引進行升/降序排列。
df.sort_index() # 行索引升序
df.sort_index(axis = 1) # 列索引升序,其實就是表頭的排序是正確的
或者你對船上最大家族的人數感興趣,你也可以:
max(text['兄弟姐妹個數'] + text['父母子女個數'])
# 同樣的方法你可以看看其他感興趣的數據
Pandas的describe()
函數查看數據基本統計信息:
train_data.describe()
'''
count 樣本大小
mean 平均值
std 標准差
min 最小值
25% 樣本數據25%時候的值
50% 50%
75% 75%
max 最大值
'''
通過describe()函數我們可以簡單地看出哪些是數值型數據哪些是字符型數據,對於字符型數據我們當然要轉換成數值型數據來處理,比如可以轉換成0-1編碼的數值型。
但需要注意的是,對於一些數值型數據卻未必就不需要進一步的處理了,比如Pclass特征,從名字我們就可以看出這是標識倉位等級的特征,取值范圍為[1, 2, 3],這個特征我們不應該簡單地當作一個數值型數據放進分類模型中直接跑,應該把它轉變為one-hot編碼,標識乘客不同的倉位,這一步我們將在數據預處理步驟完成。
另外,你也可以單獨看看特定列的信息統計:
text['父母子女個數'].describe() # 或許可以看出訊息,絕大多數乘客都沒有帶父母子女
text['票價'].describe()
課后思考
1. read_table和read_csv的異同
read_csv是pandas中專門用於csv文件讀取的功能,不過這並不是唯一的處理方式。pandas中還有讀取表格的通用函數read_table。兩者都是加載帶分隔符的數據,每一個分隔符作為一個數據的標志,但二者讀出來的數據格式是不一樣的。
兩者在讀取數據時的主要差異性如下:
默認分隔符 | 使用方式 | 輸出結果 | |
---|---|---|---|
read_csv | 逗號 | pd.read_csv( ) |
每一個字符串作為一列 |
read_table | 制表符'\t' | pd.read_table |
每個字符串之間有逗號相隔 |
由於read_table以制表符 \t 作為數據的標志,也就是以行為單位進行存儲。因此在讀取數據的過程中:
df_csv = pd.read_csv(path)
df_table = pd.read_table(path)
print(df_csv.shape) # (891, 12)
print(df_table.shape) # (891, 1)
輸出結果表明,使用read_table是對每一行作為一個維度進行了存儲,可以得到一個n行1列的數組,每一行字符串為一列而不是每一個字符串。而使用read_csv是一個n行k列的數組,因為它將每一個字符串作為了一列。