數(shù)據(jù)收集及讀取
數(shù)據(jù)收集
- 數(shù)據(jù)接口 -- 一些網(wǎng)站有API接口沙咏,通過(guò)相應(yīng)的API請(qǐng)求方式就能獲取到想要的數(shù)據(jù)肮疗,一般情況下數(shù)據(jù)會(huì)非常規(guī)范,完整童番。
- 數(shù)據(jù)庫(kù) -- 需要得到授權(quán)。
- 數(shù)據(jù)爬蟲(chóng) -- 優(yōu)勢(shì)在于你無(wú)需數(shù)據(jù)擁有者提供權(quán)限威鹿,缺點(diǎn)是獲取到的數(shù)據(jù)特征有限剃斧,往往會(huì)有更多丟失或錯(cuò)誤數(shù)據(jù)。
數(shù)據(jù)讀取
1.數(shù)據(jù)文件讀取
數(shù)據(jù)文件忽你,最常見(jiàn)到的有.csv, .txt幼东,少見(jiàn)有.xlsx格式的文件。對(duì)于存在本地的.csv, .txt數(shù)據(jù)文件,首先用open()方法:
file = open("xxx.csv", 'r')
for line in file:
print(line)
對(duì)于excel支持的.xlsx文件需要安裝xlrd包:
sudo pip3 install xlrd
import xlrd
file = xlrd.open_workbook("xxx.xlsx")
# 按索引讀取表
table = file.sheet_by_index(0)
# 讀取每行并打印
for i in range(table.nrows):
print(table.row_values(i))
open方法的局限很多根蟹。所以大多數(shù)情況下都會(huì)數(shù)據(jù)預(yù)處理神器Pandas來(lái)完成數(shù)據(jù)文件的讀取工作脓杉。
import pandas as pd
df = pd.read_csv("xxx.csv")
print(df)
使用Pandas讀取文件方便,代碼簡(jiǎn)潔简逮,讀取的數(shù)據(jù)直接就是DataFrame球散。
除了csv文件,Pandas還可以讀取其他文件:
# JSON文件
pd.read_json
# HTML文件
pd.read_html
# 本地剪切板
pd.read_clipboard
# MS Excel文件
pd.read_excel
# HDF5Format文件
pd.read_hdf
# Feather 格式
pd.read_feather
# Msgpack
pd.read_msgpack
# Stata
pd.read_stata
# SAS
pd.read_sas
# Python Pickle格式
pd.read_pickle
# SQL數(shù)據(jù)庫(kù)
pd.read_sql
# Google Big Query
pd.read_gbq
對(duì)于Pandas讀取數(shù)據(jù)方法散庶,還帶有很多參數(shù)蕉堰。比如txt格式的文件:
df = pd.read_table("xxx.txt", header=0, sep='\t')
print(df)
這里,header=0表示將第一行設(shè)為表頭悲龟,而sep='\t'則代表使用空格分隔字段屋讶。
2.數(shù)據(jù)庫(kù)讀取
除了數(shù)據(jù)文件,如果想要讀取 MySQL须教,Oracle皿渗,Microsoft SQL 等數(shù)據(jù)庫(kù)里面的數(shù)據(jù)。一般情況下都需要安裝相應(yīng)的第三方庫(kù)没卸。例如,讀取 MySQL 時(shí)秒旋,我們需要安裝 MySQLdb:
sudo apt-get install python-dev libmysqlclient-dev
sudo pip install MySQL-python
安裝之后啟動(dòng)mysql服務(wù):
sudo service mysql start
然后使用root用戶(hù)登陸:
mysql -u root -p
向數(shù)據(jù)庫(kù)寫(xiě)入一些數(shù)據(jù):
# 創(chuàng)建名為xxx的數(shù)據(jù)庫(kù)
mysql> CREATE DATABASE xxx;
Query OK, 1 row affected (0.01 sec)
# 切換到該庫(kù)
mysql> use xxx
Database changed
# 創(chuàng)建名為person的表
mysql> CREATE TABLE person (id int(10),name char(20),phone int(12));
Query OK, 0 rows affected (0.06 sec)
# 寫(xiě)入示例數(shù)據(jù)1
mysql> INSERT INTO person VALUES(01,'Tom',110110110);
Query OK, 1 row affected (0.02 sec)
# 寫(xiě)入示例數(shù)據(jù)2
mysql> INSERT INTO person VALUES(02,'Jack',119119119);
Query OK, 1 row affected (0.02 sec)
# 寫(xiě)入示例數(shù)據(jù)3
mysql> INSERT INTO person VALUES(03,'Rose',112222119);
Query OK, 1 row affected (0.01 sec)
通過(guò)MySQLdb連接并讀取數(shù)據(jù)约计。
>>> import MySQLdb
# 連接數(shù)據(jù)庫(kù)
>>> db = MySQLdb.connect(host="localhost", user="root", passwd="", db="xxx")
# 獲取操作游標(biāo)
>>> cur = db.cursor()
# 使用 execute 方法執(zhí)行 SQL 查詢(xún)語(yǔ)句
>>> cur.execute("SELECT * FROM person")
3L
# 輸出查詢(xún)
>>> for row in cur.fetchall():
... print row # 注意縮進(jìn)
...
(1L, 'Tom', 110110110L)
(2L, 'Jack', 119119119L)
(3L, 'Rose', 112222119L)
# 關(guān)閉數(shù)據(jù)庫(kù)連接
>>> db.close()
數(shù)據(jù)預(yù)處理
數(shù)據(jù)概覽
Pandas為我們提供了相應(yīng)的函數(shù)。通過(guò)這些函數(shù)方法迁筛,我們可以很方便的概覽數(shù)據(jù)煤蚌。
import pandas as pd
df = pd.read_csv("test.csv")
# 瀏覽頭部數(shù)據(jù)
df.head()
# 瀏覽尾部數(shù)據(jù)
df.tail()
# 不帶參數(shù)的head()和tail()方法默認(rèn)顯示5條數(shù)據(jù),
# 也可以自定義顯示數(shù)據(jù)條數(shù)
df.head(10)
# describe()方法可以對(duì)數(shù)據(jù)集中的數(shù)值進(jìn)行統(tǒng)計(jì)细卧,
# 會(huì)輸出數(shù)據(jù)計(jì)數(shù)尉桩,最大值,最小值等
df.describe()
count()方法可以用于計(jì)算數(shù)據(jù)集中非空數(shù)據(jù)的數(shù)量:
df.count()
缺失值處理
缺失值是指數(shù)據(jù)集中的某一些行或列出現(xiàn)數(shù)值丟失贪庙。造成這種現(xiàn)象的原因蜘犁,有可能是數(shù)據(jù)沒(méi)有采集成功,或者是因?yàn)閭鬏斨褂省⒋鎯?chǔ)出現(xiàn)故障这橙。
1.查找缺失值
查找缺失值,我們依舊可以使用 Pandas 進(jìn)行處理导披。Pandas 中屈扎,缺失數(shù)據(jù)一般采用NaN標(biāo)記NaN 代表 Not a Number。特別地撩匕,在時(shí)間序列里鹰晨,時(shí)間戳的丟失采用 NaT 標(biāo)記。
Pandas 用于檢測(cè)缺失值主要用到兩個(gè)方法,分別是:isnull() 和 notnull()模蜡,故名思意就是「是缺失值」和「不是缺失值」漠趁。默認(rèn)會(huì)返回布爾值用于判斷。
import pandas as pd
df = pd.read_csv("test.csv")
print(df.head(10).isnull())
print(df.head(10).notnull())
2.刪除缺失值所在的列或行
刪除缺失值是最簡(jiǎn)單直接的辦法之一哩牍。它適用于三種情況:
缺失值少棚潦,對(duì)數(shù)據(jù)集的影響可以忽略不計(jì)。這句話(huà)的意思應(yīng)該很好理解膝昆。比如一個(gè)數(shù)萬(wàn)行的數(shù)據(jù)集丸边,恰好有某幾行缺失了幾個(gè)特征值。缺失的數(shù)據(jù)行遠(yuǎn)遠(yuǎn)小于全部數(shù)據(jù)的數(shù)量荚孵,且刪除這幾行之后妹窖,對(duì)原數(shù)據(jù)集的影響可以忽略。這時(shí)候收叶,直接刪除缺失值所在的行是最好的骄呼。
缺失數(shù)據(jù)量大,已無(wú)法挽救判没。舉個(gè)例子蜓萄,一個(gè)數(shù)據(jù)集有1 萬(wàn)行,存在 10 個(gè)特征列澄峰。其中某一項(xiàng)特征所在的列存在 9000 個(gè)空值嫉沽。這也就表明該列存在的意義已經(jīng)不大了。所以也需要?jiǎng)h除數(shù)據(jù)俏竞。
該缺失值無(wú)法被填充绸硕。這種情況也很常見(jiàn)。就拿我們上面一直在用的 test_file.csv 數(shù)據(jù)集距離魂毁。該數(shù)據(jù)集實(shí)際為洛杉磯人口普查數(shù)據(jù)玻佩。我們可以看到數(shù)據(jù)集中有一列為 Zip Code,也就是郵編席楚。郵編是客觀(guān)存在的咬崔,也是不能隨意更改的。如果某幾項(xiàng)郵編缺失烦秩,你是無(wú)法隨意通過(guò)一些數(shù)值來(lái)填充郵編刁赦。所以,對(duì)應(yīng)這樣的數(shù)據(jù)行已經(jīng)沒(méi)有意義闻镶,選擇直接刪除往往是最好的甚脉。
刪除缺失值所在的列或行非常簡(jiǎn)單,使用Pandas提供的 dropna() 方法铆农。dropna() 方法可以將有缺失值的行或列全部移除牺氨。當(dāng)然狡耻,你可以使用 axis=0 參數(shù)指定行,或 axis=1 參數(shù)指定列:
import pandas as pd
df = pd.read_csv("xxx.csv")
print(df.dropna(axis=0))
print(df.dropna(axis=1))
因?yàn)榭赡苊恳涣卸加锌罩岛锇迹詣h除列要慎用夷狰。
3.填充缺失值
除了刪除缺失值,對(duì)缺失值處理的另外一種方法就是填充缺失值郊霎。如果你第一次接觸缺失值處理沼头,你可能會(huì)認(rèn)為填充缺失值的處理好于直接刪除缺失值。其實(shí)并不一定书劝,原因在于填充缺失值會(huì)直接改變?cè)袛?shù)據(jù)集进倍,這可能會(huì)影響后續(xù)預(yù)測(cè)分析的結(jié)果。所以购对,使用填充缺失值時(shí)一定要更加謹(jǐn)慎猾昆。
一般情況下,填充缺失值有三種方法骡苞。
手動(dòng)填充垂蜗。手動(dòng)填充雖然是笨辦法,但往往是效果最好的方法解幽。手動(dòng)填充非常適合于一種情形贴见,那就是數(shù)據(jù)可以被人為有效確定。舉個(gè)例子:上面的洛杉磯人口普查數(shù)據(jù)表中躲株,第一列為郵編片部,它用于標(biāo)記不同的地區(qū)。如果郵編有幾項(xiàng)數(shù)據(jù)缺失徘溢,那么通過(guò)手動(dòng)篩選再填充郵編就是最適合的方法吞琐。原因在于捆探,郵編和其他數(shù)據(jù)不一樣然爆,如果它不存在或不正確,就直接導(dǎo)致這行數(shù)據(jù)無(wú)效黍图,甚至影響到其他數(shù)據(jù)曾雕。手動(dòng)填充,充分展現(xiàn)了人的靈活性助被,但同樣是一個(gè)費(fèi)時(shí)費(fèi)力的辦法剖张。
臨近填充。 臨近填充揩环,故名思意就是采用與缺失值相鄰的數(shù)據(jù)進(jìn)行填充缺失值的方法搔弄。臨近填充比較適合于零散的不確定數(shù)據(jù)。零散丰滑,指的是不會(huì)連續(xù)缺失數(shù)十個(gè)或上百個(gè)數(shù)據(jù)值顾犹。如果連續(xù)缺失的值太多,你用臨近填充將其變?yōu)橥粩?shù)據(jù)值,這對(duì)數(shù)據(jù)集整體的影響可想而知炫刷。不確定數(shù)據(jù)擎宝,就是通過(guò)視覺(jué)觀(guān)察,無(wú)法發(fā)現(xiàn)相鄰數(shù)據(jù)之間有什么聯(lián)系浑玛,前后數(shù)據(jù)時(shí)大時(shí)小绍申,無(wú)法被人為確定或找出規(guī)律。
Pandas 提供了用于臨近填充的fillna()方法顾彰。該方法的使用示例如下:
import pandas as pd
# 被前面的臨近值填充
df = pd.read_csv("xxx.csv")
print(df.head(10).fillna(method='pad'))
#被后面的臨近值填充
df = pd.read_csv("xxx.csv")
print(df.head(10).fillna(method='bfill'))
fillna()方法在填充時(shí)并不會(huì)影響原有的數(shù)據(jù)集极阅。
- 插值填充。插值填充就是采用數(shù)學(xué)的方法對(duì)數(shù)據(jù)進(jìn)行插值拘央。舉個(gè)例子涂屁,有一列數(shù)據(jù)為 [2011, 2012, 2013, 缺失值, 缺失值, 2016, 2017] 。這里灰伟,無(wú)論你采用向前還是向后填充拆又,其實(shí)都不是最好的。你可以發(fā)現(xiàn)數(shù)據(jù)是一個(gè)等差數(shù)列栏账,缺失值應(yīng)該分別為[2014, 2015]帖族,這也就是一個(gè)線(xiàn)性插值的過(guò)程。
Pandas 提供了相關(guān)插值方法挡爵,通過(guò)interpolate()方法實(shí)現(xiàn)竖般。默認(rèn)為參數(shù)為線(xiàn)性插值,即 method='linear'茶鹃。舉例:
import pandas as pd
df = pd.read_csv("xxx.csv")
print(df.interpolate().head(10))
除此之外涣雕,interpolate()方法還有{‘linear’, ‘time’, ‘index’, ‘values’, ‘nearest’, ‘zero’, ‘slinear’, ‘quadratic’, ‘cubic’, ‘barycentric’, ‘krogh’, ‘polynomial’, ‘spline’, ‘piecewise_polynomial’, ‘from_derivatives’, ‘pchip’, ‘a(chǎn)kima’}等插值方法可供選擇。
- 如果你的數(shù)據(jù)增長(zhǎng)速率越來(lái)越快闭翩,可以選擇 method='quadratic'二次插值挣郭。
- 如果數(shù)據(jù)集呈現(xiàn)出累計(jì)分布的樣子,推薦選擇 method='pchip'疗韵。
- 如果需要填補(bǔ)缺省值兑障,以平滑繪圖為目標(biāo),推薦選擇 method='akima'蕉汪。
- 另外流译,method='akima',method='barycentric' 和 method='pchip' 需要 Scipy 才能使用者疤。
獨(dú)熱編碼
在對(duì)數(shù)據(jù)的預(yù)處理過(guò)程中福澡,我們會(huì)遇到有一些特征列中的樣本并不是連續(xù)存在的,而是以分類(lèi)形式存在的情況驹马。例如革砸,某一裝置的狀態(tài)有三種情況眯搭,分別為:正常、機(jī)械故障业岁、電路故障鳞仙。如果我們要將這些數(shù)據(jù)運(yùn)用到后續(xù)的預(yù)測(cè)分析中,就需要對(duì)文字狀態(tài)進(jìn)行轉(zhuǎn)換笔时。一般情況下棍好,可以用 0 表示正常,1 代表機(jī)械故障允耿,2 代表電路故障借笙。
但是這種映射方式,往往會(huì)讓學(xué)習(xí)器認(rèn)為 2 代表電路故障比 1 代表機(jī)械故障更「大」较锡,從而影響模型分析結(jié)果业稼,這肯定是不行的。
所以蚂蕴,對(duì)于以分類(lèi)形式存在的特征變量低散,我們會(huì)采用一種叫獨(dú)熱編碼(One-Hot Encoding)的方式將其轉(zhuǎn)換成二元特征編碼,進(jìn)一步對(duì)特征進(jìn)行了稀疏處理骡楼。獨(dú)熱編碼采用位狀態(tài)寄存器來(lái)對(duì)個(gè)狀態(tài)進(jìn)行編碼熔号,每個(gè)狀態(tài)都由他獨(dú)立的寄存器位,并且在任意時(shí)候只有一位有效鸟整。舉例如下:
Pandas提供了更簡(jiǎn)單的方式來(lái)處理以分類(lèi)形式的變量引镊。可以通過(guò)get_dummies()將以分類(lèi)形式存在的變量轉(zhuǎn)換為獨(dú)熱編碼篮条。
import pandas as pd
df = pd.read_csv("one_hot_demo.csv", header=0)
df.head(10)
在此演示文件中弟头,status共有none, electric, engine三類(lèi)數(shù)值。color有red和green兩類(lèi)涉茧。
oneHot = pd.get_dummies(df[['status', 'color']])
oneHot.head(10)
字符串被進(jìn)行了獨(dú)熱編碼赴恨,特征也從原先的2列拓充為5列。所以降瞳,獨(dú)熱編碼好處多多嘱支。
重復(fù)值處理
pandas.Dataframe.duplicated()可以用來(lái)標(biāo)識(shí)重復(fù)數(shù)據(jù)蚓胸,數(shù)據(jù)集中的重復(fù)數(shù)據(jù)行會(huì)返回布爾類(lèi)型True挣饥。
上面的獨(dú)熱編碼示例數(shù)據(jù)中存在大量重復(fù)數(shù)據(jù),就拿它來(lái)舉例:
import pandas as pd
df = pd.read_csv("one_hot_demo.csv", header=0)
print(pd.DataFrame.duplicated(df).head(10))
pandas.DataFrame.drop_duplicates()可以返回一個(gè)去重后的數(shù)據(jù)集沛膳。
import pandas as pd
df = pd.read_csv("one_hot_demo.csv", header=0)
print(pd.DataFrame.drop_duplicates(df))
去重后的數(shù)據(jù)集如下扔枫,僅有6行非重復(fù)項(xiàng)。
異常值檢測(cè)
一種簡(jiǎn)單直觀(guān)的異常值檢測(cè)方法锹安,那就是通過(guò)箱形圖(箱線(xiàn)圖)來(lái)識(shí)別異常數(shù)據(jù)短荐。箱形圖是用來(lái)觀(guān)測(cè)數(shù)據(jù)集分布的一種圖形類(lèi)型倚舀。箱形圖中,從上到下依次有 6 個(gè)數(shù)據(jù)節(jié)點(diǎn)忍宋,分別是上界痕貌、上四分位、均值糠排、中位數(shù)舵稠、下四分位、下界入宦。而那些超過(guò)上界的值就會(huì)被標(biāo)記為離群點(diǎn)哺徊,也就是異常數(shù)據(jù)。
from matplotlib import pyplot as plt
import pandas as pd
data = pd.read_csv("test_file.csv", header=0)
Total_Population = data["Total_Population"]
plt.boxplot(Total_Population)
plt.show()
將離群點(diǎn)標(biāo)記并導(dǎo)出:
from matplotlib import pyplot as plt
import pandas as pd
data = pd.read_csv("test_file.csv", header=0)
Total_Population = data["Total_Population"]
P = plt.boxplot(Total_Population)
outlier = P['fliers'][0].get_ydata()
print(outlier)
DataFrame帶有boxplot()方法可以很方便地將所有列數(shù)據(jù)的箱形圖畫(huà)在一張圖中對(duì)比:
from matplotlib import pyplot as plt
import pandas as pd
data = pd.read_csv("test_file.csv", header=0)
data.boxplot()
plt.show()