本文為Datawhale8月組隊(duì)學(xué)習(xí)——?jiǎng)邮謱W(xué)數(shù)據(jù)分析課程的系列學(xué)習(xí)筆記宵晚。
Datawhale-動(dòng)手學(xué)數(shù)據(jù)分析
數(shù)據(jù)來源
Kaggle小白入門首選練手項(xiàng)目——Kaggle-泰坦尼克號(hào)存活率
Ch1 數(shù)據(jù)加載與探索性分析
數(shù)據(jù)分析包含數(shù)據(jù)加載育苟、探索性數(shù)據(jù)分析鼻种、數(shù)據(jù)清洗灭红、特征處理、數(shù)據(jù)建模口注、模型評(píng)估等多個(gè)步驟变擒。在進(jìn)行數(shù)據(jù)分析之前,需要載入我們獲取的數(shù)據(jù)集寝志,并通過探索性分析初步了解數(shù)據(jù)的結(jié)構(gòu)娇斑、組成和特征。
Ch1-1 數(shù)據(jù)載入與初步觀察
數(shù)據(jù)載入
載入函數(shù)
對(duì)于常見的數(shù)據(jù)文件類型(.csv/.xlsx/.tsv/...)材部,通常使用第三方庫(kù)pandas載入數(shù)據(jù)毫缆。
pandas中,常見的載入數(shù)據(jù)文件函數(shù)有以下幾種:
- read_table():可以讀取常見的分隔符定界文件败富,
sep=''
參數(shù)用于選擇分隔符悔醋,若該參數(shù)為空,則不予分隔(所有數(shù)據(jù)集中在一列中)兽叮,支持正則表達(dá)式芬骄。 - read_csv():讀取逗號(hào)分隔符文件(.csv)猾愿,同樣有
sep=''
參數(shù),默認(rèn)為逗號(hào)(,) - read_excel():讀取Excel文件(.xlsx)账阻,相比前兩種函數(shù)蒂秘,對(duì)于含有多個(gè)工作簿的excel文件,一般需要輸入?yún)?shù)
sheetname=''
淘太,不輸入則默認(rèn)為第一張工作簿
以上函數(shù)默認(rèn)返回DataFrame對(duì)象姻僧,對(duì)于excel,當(dāng)讀入多個(gè)工作簿(如:[1,2])時(shí)蒲牧,返回一個(gè)dict對(duì)象撇贺,每個(gè)元素的值都是一個(gè)DataFrame對(duì)象。
除此之外冰抢,pandas還支持讀取很多其他的文件格式(如:JSON松嘶、pickle、SQL以及常見統(tǒng)計(jì)軟件STATA/SPSS的輸出格式)挎扰,具體參考pandas官方文檔-IO
相對(duì)路徑與絕對(duì)路徑
查看當(dāng)前所在路徑的命令:os.getcwd()
使用前要導(dǎo)入python自帶的輸入輸出庫(kù)os
相對(duì)路徑表述:
符號(hào) | 含義 |
---|---|
/ | 根目錄 |
./ | 當(dāng)前目錄 |
../ | 上一級(jí)目錄 |
../../ | 上兩級(jí)目錄翠订,多級(jí)目錄以此類推 |
逐塊讀取
當(dāng)數(shù)據(jù)文件過大,包含數(shù)據(jù)量過多時(shí)遵倦,為了防止一次性讀入所有數(shù)據(jù)服務(wù)器內(nèi)存占用過大尽超,難以處理,pandas的載入函數(shù)提供了chunksize
參數(shù)以實(shí)現(xiàn)數(shù)據(jù)的逐塊讀取梧躺,該參數(shù)使得函數(shù)通過分多次將文件數(shù)據(jù)讀入內(nèi)存似谁,降低了內(nèi)存占用。
# 逐塊讀取
chunks = pd.read_csv('../../Titanic-kaggle/data/train.csv', chunksize = 1000)
print(type(chunks))
for piece in chunks:
print(type(piece))
print(len(piece))
當(dāng)使用chunksize
參數(shù)時(shí)燥狰,載入函數(shù)將返回TextFileReader對(duì)象棘脐,該對(duì)象可以使用for語句遍歷,其中每個(gè)元素都是一個(gè)包含指定行數(shù)的DataFrame對(duì)象龙致,此時(shí)就可以在循環(huán)中實(shí)現(xiàn)對(duì)各塊數(shù)據(jù)的批處理蛀缝。
設(shè)定列名和索引
- 可以在讀取數(shù)據(jù)文件時(shí)利用參數(shù)
names=[]
、header=0
目代、index='index_col_name'
設(shè)定屈梁。 - 也可以在后期通過方法
df.set_index()
、df.rename(colomns={})
或借助屬性df.columns
榛了、df.index
暴力修改
Tips:
- 當(dāng)使用read_csv()的names參數(shù)修改列名時(shí)在讶,其實(shí)質(zhì)是在原表基礎(chǔ)上加上給定的列名,此時(shí)header會(huì)取Null霜大;若不使用names參數(shù)构哺,header默認(rèn)取0。因此,設(shè)定列名時(shí)曙强,應(yīng)當(dāng)使用header=0來表明原數(shù)據(jù)有列名残拐,且位于第一行,這樣才能實(shí)現(xiàn)列名的替換碟嘴。
- df.set_index()中包含drop參數(shù)溪食,該參數(shù)應(yīng)設(shè)定為True,表示刪除現(xiàn)有索引列娜扇,否則當(dāng)前索引行將變?yōu)槠胀屑尤氍F(xiàn)有DataFrame
# 方法1:讀取時(shí)設(shè)定
names = ['乘客ID','是否幸存','乘客等級(jí)(1/2/3等艙位)','乘客姓名','性別','年齡','堂兄弟/妹個(gè)數(shù)','父母與小孩個(gè)數(shù)','船票信息','票價(jià)','客艙','登船港口']
# header屬性用于設(shè)置列名取自哪一行错沃,指定names時(shí)應(yīng)當(dāng)設(shè)為0,否則會(huì)多出原標(biāo)題行
df = pd.read_csv('../../Titanic-kaggle/data/train.csv',names= names,index_col='乘客ID',header=0)
# 方法2:更改表頭和索引
column_names = {'PassengerId':'乘客ID','Survived':'是否幸存','Pclass':'乘客等級(jí)(1/2/3等艙位)','Name':'乘客姓名','Sex':'性別','Age':'年齡','SibSp':'堂兄弟/妹個(gè)數(shù)','Parch':'父母與小孩個(gè)數(shù)','Ticket':'船票信息','Fare':'票價(jià)','Cabin':'客艙','Embarked':'登船港口'}
df.rename(columns = column_names, inplace = True)
df.set_index('乘客ID', drop = True, inplace = True)
初步觀察
概覽數(shù)據(jù)基本信息
查看數(shù)據(jù)的基本信息主要用到以下一些方法和屬性:
方法/屬性 | 用途 |
---|---|
df.shape | 以元組形式返回dataframe對(duì)象的行列數(shù) |
df.size | 以整數(shù)形式返回dataframe對(duì)象的元素?cái)?shù)(不包含索引/表頭) |
df.colomns | 輸出所有的列名 |
df.head(n)/df.tail(n) | 查看dataframe前n行/后n行 |
df.info() | 輸出關(guān)于數(shù)據(jù)的基本描述雀瓢,包含行數(shù)枢析、各列的列名、數(shù)據(jù)類型致燥、非空值數(shù)以及占用內(nèi)存登疗。其中verbose參數(shù)可以用于選擇長(zhǎng)/短兩種描述 |
df.describe() | 輸出各列的描述性統(tǒng)計(jì)信息排截,可以迅速查看數(shù)據(jù)的統(tǒng)計(jì)特征(Series也有該方法) |
df.value_counts() | 返回一個(gè)包含不同列各值數(shù)的Series(Series也有該方法) |
判斷缺失值
用到兩個(gè)方法:
- df.isnull():返回一個(gè)判斷是否為空的DataFrame嫌蚤,若為空則為True,反之為False
- df.isnotnull():返回一個(gè)判斷是否為非空的DataFrame断傲,若為非空則為True脱吱,反之為False
數(shù)據(jù)輸出
與讀取的幾個(gè)函數(shù)類似,語法基本一致认罩,區(qū)別在于數(shù)據(jù)輸出使用的是對(duì)象的方法箱蝠,而非函數(shù):
- df.to_csv()
- df.to_excel()
Notes:
- 查閱API文檔,發(fā)現(xiàn)沒有to_table()方法垦垂,很神奇的是pandas自帶了to_latex()和to_markdown()方法
- 一般會(huì)設(shè)置編碼方式參數(shù)
encoding='utf-8'
宦搬,當(dāng)元素含有中文時(shí),若出現(xiàn)亂碼劫拗,可以嘗試使用utf_8_sig或gbk格式
Ch1-2 pandas基礎(chǔ)
數(shù)據(jù)類型
pandas最基本的兩種數(shù)據(jù)類型:DataFrame和Series间校。此外還需要了解numpy中的基本數(shù)據(jù)類型——ndarray。
ndarray:numpy中最基礎(chǔ)的數(shù)據(jù)類型页慷,多維數(shù)組對(duì)象憔足,本質(zhì)上就是一個(gè)n維矩陣。只能存放同類型數(shù)據(jù)酒繁。
Series:主要由兩部分組成滓彰,index 和 values。index可以是任意類型州袒,不一定非是數(shù)字類型揭绑,values是存放的內(nèi)容,是一個(gè)1維的ndarray
-
DataFrame: 可以看作由多列Series組成郎哭,也可以看作由多行Series組成他匪」眩或者可以看作columns, index, values這三部分組成。
- columns:列名诚纸,默認(rèn)也是數(shù)字升序撰筷,可以是任意類型
- index:行名,默認(rèn)數(shù)字升序畦徘,可以是任意類型
- values:存放的內(nèi)容毕籽,是一個(gè)2維的ndarray
簡(jiǎn)單來說,Series實(shí)質(zhì)是一維數(shù)組井辆,DataFrame則是多個(gè)Series組成的二維數(shù)組关筒,當(dāng)然二者相比ndarray要多出一些如索引、列名等的屬性杯缺,可以看作ndarray的包裝蒸播。
官方文檔里寫到二者的關(guān)系:
DataFrame can be thought of as a dict-like container for Series objects.(DataFrame可以看作一個(gè)類似dict的用于盛放Series的容器)
構(gòu)造方法
Series
- List + index_list
- Dict
- ndarray + index_list
使用 List 進(jìn)行創(chuàng)建,自動(dòng)添加0開始的行標(biāo)簽(索引)
Series 創(chuàng)建時(shí)若不注明 name
參數(shù)萍肆,相當(dāng)于此列沒有列名
## Series的創(chuàng)建
# 01 使用list
sdata = [2000,500,1000,4000]
example_1 = pd.Series(sdata)
# 02 使用dict
sdata = {'thu':1,'zju':3,'hust':8,'whu':9,'sysu':10}
example_1 = pd.Series(sdata)
example_1
# 03 使用np.ndarray
sdata = np.random.rand(10)*20
example_1 = pd.Series(sdata,index=['a','b','c','d','e','f','g','h','i','j'],name='random')
無論是字典袍榆,列表還是元組,都可以構(gòu)建Series塘揣。只不過包雀,dict自帶index,而list亲铡,tuple要專門定義index(也就是每一行的行名)才写。系統(tǒng)默認(rèn)的index為0,1,2,3…
DataFrame
DataFrame的創(chuàng)建方法有很多種,這里只列了其中幾種奖蔓,具體可以參考創(chuàng)建DataFrame的7種方法
- DataFrame(Dict):字典內(nèi)可以為列表/字典/Series
- DataFrame.from_dict(Dict)
- DataFrame(np.ndarray)
可以添加index
和columns
參數(shù)赞草,不附帶index
參數(shù)則索引默認(rèn)為自然數(shù)序列
## DataFrame的創(chuàng)建
# 01 使用dict,其中key為list(亦可字典套字典)
ddata = {'country':['US','Brazil','India','Europe','South Africa'],'confirmed':[5481795,3407354,2702742,930276,592744],'death':[171799,109888,51797,15836,12264]}
example_2 = pd.DataFrame(ddata)
print(example_2)
print('--------------')
# 02 from_dict()靜態(tài)方法
example_2 = pd.DataFrame.from_dict(ddata)
print(example_2)
print('--------------')
# 03 二維數(shù)組
ddata = np.array([4,1,4,5,5,2,3,5,6,3,3,4,6,1,9]).reshape(5,3)
example_2 = pd.DataFrame(ddata, index=list('abcde'), columns=['four', 'one', 'three'])
print(example_2)
有些時(shí)候我們只需要選擇dict中部分的鍵當(dāng)做DataFrame的列吆鹤,那么我們可以使用columns參數(shù)厨疙,例如我們只選擇country和death列:
pd.DataFrame(data = ddata,columns=['country','death'])
數(shù)據(jù)操作
列選取
- 作為屬性選取:
df.Cabin
- 使用[]運(yùn)算符檀头,其實(shí)現(xiàn)方式是實(shí)現(xiàn)類的_getitem_魔術(shù)方法:
df['Cabin']
很多時(shí)候會(huì)截取所有數(shù)據(jù)的一部分進(jìn)行后續(xù)操作和分析轰异,這個(gè)時(shí)候很可能需要用到
reset_index(drop=True)
方法來重新生成數(shù)字索引
行/列刪除
- df.drop():
axis
參數(shù)默認(rèn)為0,即刪除行暑始,要改成列應(yīng)改為1搭独。或者忽略axis
直接使用columns
參數(shù) - del df['']:del操作符廊镜,只能用于列
很多操作方法都有
inplace
參數(shù)牙肝,inplace
為True表示直接在原對(duì)象上進(jìn)行改動(dòng),默認(rèn)為False,返回一個(gè)新對(duì)象
數(shù)據(jù)篩選
Pandas有自帶的訪問器操作配椭,loc
與 iloc
iloc
基于位置(數(shù)字索引)選擇虫溜,通過其在 DataFrame 中的數(shù)字排位進(jìn)行訪問。
loc
則通過自定義標(biāo)簽進(jìn)行提取股缸,該方法聚焦于數(shù)據(jù)的標(biāo)簽(索引)而不是位置(數(shù)字索引)衡楞。
## iloc
# 取出第一行的內(nèi)容
df.iloc[0]
# 取出第一列的內(nèi)容
df.iloc[:, 0]
# 也可以采用內(nèi)嵌列表的方式
df.iloc[[0, 1, 2], 0]
## loc
# 選中第一行的Sex列對(duì)應(yīng)的單元格
df.loc[0, 'Sex']
# 選中Pclass, Name, Sex這三列的數(shù)據(jù)
df.loc[:, ['Pclass', 'Name', 'Sex']]
可以使用負(fù)數(shù)來進(jìn)行選擇:
# 選擇倒數(shù)五行的內(nèi)容
df.iloc[-5:]
Notes:
二者的使用方法都是使用中括號(hào)
[]
而不是小括號(hào)()
loc
與iloc
均采用了先選行后選列的語法,這與傳統(tǒng)的 python 語法相反二者的區(qū)別
iloc
的區(qū)間滿足前閉后開敦姻,而loc
則滿足前閉后閉瘾境。因而當(dāng)我們遇到 String 類型索引,需要按照索引進(jìn)行選取內(nèi)容時(shí)镰惦,我們往往是希望取出區(qū)間內(nèi)所有的元素迷守,此時(shí)更好的方法是使用loc
特定條件篩選
loc
訪問器操作和[]
運(yùn)算符可以根據(jù)輸入的邏輯值Series來篩選顯示的行,將自動(dòng)從中選取邏輯值為True的行旺入。
一些常見的邏輯相關(guān)符號(hào)和方法:
- 用于連接多個(gè)條件的符號(hào):使用 & 表示邏輯和兑凿,使用 | 表示邏輯或
- df.isin([]):用于判斷是否包含在XXX內(nèi),相當(dāng)于SQL語言中的 WHERE ... IN...
- df.isnull():用于判斷是否為空值
- df.notnull():用于判斷是否非空
# []運(yùn)算符
df[(df['Age']>10) & (df['Age']<50)]
# loc訪問器操作
df.loc[df['Cabin'].isin(['C123','C85'])]
Ch1-3 探索性數(shù)據(jù)分析
數(shù)據(jù)排序
可以按值排序茵瘾,也可以按索引排序礼华。
String
類型自動(dòng)按字母順序排序。
- sort_values():按值排序龄捡,
by=[<列1>卓嫂,<列2>]
參數(shù)用于選擇排序依據(jù)列,可以按多列進(jìn)行綜合排序 - sort_index():按索引排序聘殖,
axis
用于選擇按行索引/列索引排序,默認(rèn)為0(列索引)
二者都有控制升降序的參數(shù)
ascending=True
行瑞,True表示按升序奸腺,F(xiàn)alse表示按降序
一些探索性發(fā)現(xiàn)
通過使用describe()
、info()
血久、corr()
突照、value_counts()
等函數(shù)對(duì)數(shù)據(jù)進(jìn)行探索性分析,有以下一些發(fā)現(xiàn):
- 船艙信息中存在大量缺失值氧吐,年齡信息也有一部分缺失讹蘑,需要對(duì)這些缺失值做一定的處理。
- 性別數(shù)據(jù)需處理為0/1變量筑舅。
得到的一些信息:
- 大多數(shù)乘客的家庭成員都很少座慰。
- 乘客姓名第一個(gè)單詞相同者擁有相同的船票信息、票價(jià)翠拣、登船港口版仔、客艙、家庭成員人數(shù),這些人應(yīng)該屬于同一個(gè)家族蛮粮。大家族成員的存活率普遍偏低益缎,因此,可以將家庭人數(shù)指標(biāo)納入后續(xù)的模型中然想。
- 乘客整體的平均年齡在29.7歲莺奔。相比整體數(shù)據(jù),幸存人群大約只占所有人的1/3变泄。觀察其中幾個(gè)方差較小的指標(biāo)弊仪,其中,幸存人數(shù)的乘客等級(jí)整體偏高杖刷。表明乘客等級(jí)確實(shí)與幸存率有著一定的關(guān)系励饵。
- 票價(jià)整體偏低,按照乘客艙位等級(jí)和年齡降序排序滑燃,發(fā)現(xiàn)前20中只有一人存活役听,這可能暗含著艙位較低的死亡風(fēng)險(xiǎn)更高的信息,猜測(cè)可能是艙位低安全措施越不足表窘,安全風(fēng)險(xiǎn)更高的原因典予。在相關(guān)系數(shù)的分析中,票價(jià)與乘客等級(jí)負(fù)相關(guān)性較強(qiáng)乐严,符合常識(shí)瘤袖,可以考慮將二者結(jié)合為一個(gè)新的綜合指標(biāo),進(jìn)一步分析該指標(biāo)和是否存活的關(guān)系昂验。
- 盡管船上的男性多于女性捂敌,女性的存活率卻明顯高于男性,女性存活率約為74.2%既琴,相比之下男性只有18.9%的存活率占婉。因此,性別可能也可以作為預(yù)測(cè)模型的考慮因素之一甫恩。