preface
在上一章節我們聊了python大數據分析的基本模塊,下面就說說2個項目吧,第一個是進行淘寶商品數據的挖掘,第二個是進行文本相似度匹配。好了,廢話不多說,趕緊上車。
淘寶商品數據挖掘
數據來源:
自己寫個爬蟲爬吧,爬到后入庫(mysql)。
數據清洗:
所謂的數據清洗,就是把一些異常的、缺失的數據處理掉,處理掉不一定是說刪除,而是說通過某些方法將這個值補充上去,數據清洗目的在於為了讓我們數據的可靠,因為臟數據會對數據分析產生影響。
拿到數據后,我們進行數據清洗分為兩方面:
- 缺失值發現:可以查找
- 異常值發現:畫圖分析
- 缺失值:在下載數據、搜集數據的時候剛好就缺失。可以通過查找的方法去發現。
- 異常值:不一定就是異常,可能就是客觀存在,但是這個值對於總的數據來說是一個就比較特殊點。可以通過畫散點圖發現。
這兩方面的處理方法如下:
- 缺失值處理:均值/中位數插補、固定值、臨近插補、回歸分析、插值法(拉格朗日插值,牛頓插值)
- 異常值處理:視為缺失,平均值修正,不處理。
方法解釋:
- 均值/中位數插補:在缺失位置插入一個總數據的均值或者中位數。
- 固定值::在缺失位置插入一個固定值
- 臨近插補:看這個缺失位置附近的值是什么,就把附近的某一個值插到缺失位置,這類應用場景應用於物以類聚的場景
- 回歸分析:等日后用上的時候在研究。
- 插值法:此算法復雜,暫未研究,等日后用上的時候在研究。
- 視為缺失:可以看成缺失值,然后通過缺失值來處理。
- 平均值修正:通過平均值來替代這個值
- 不處理:不處理這個值
開始分析:
表結構介紹:
淘寶商品表結構如下:
- title:商品名稱
- link:商品URL
- price:商品價錢
- comment:商品評論數量
mysql> desc taob;
+---------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------+-------------+------+-----+---------+-------+
| title | varchar(50) | YES | | NULL | |
| link | varchar(60) | NO | PRI | NULL | |
| price | int(30) | YES | | NULL | |
| comment | int(30) | YES | | NULL | |
+---------+-------------+------+-----+---------+-------+
對於上面四個字段,比較好處理的就是價錢和評論數,比如價錢是0(沒有采集到的數據),可以通過剛才平均值或者中位數來填充,對於異常值,比如某個評論10W+,那么也可以采用平均值修正。
Python環境介紹:
依賴於pymysql,numpy,pandas,matplotlib,請自己先安裝。可以參考我上篇博文:http://www.cnblogs.com/liaojiafa/p/6239262.html
拿代碼說話:
- 獲取數據
conn = pymysql.connect(host='192.168.56.4',user='root',passwd='123456',db='csdn',charset='utf8')
sql='select * from taob'
data = pandas.read_sql(sql,conn)
print(data.head(1))
#數據樣例如下,和mysql字段相匹配的:
0 買2袋減2元 印尼進口菲那菲娜蝦味木薯片油炸大龍蝦片零食品400g
link price comment
0 https://item.taobao.com/item.htm?id=44350560220 50 2577
可以看看數據的中位數和均值:
print(data.describe())
price comment
count 9616.00000 9616.000000
mean 64.49324 562.239601 # 均值
std 176.10901 6078.909643
min 0.00000 0.000000
25% 20.00000 16.000000
50% 36.00000 58.000000 # 中位數
75% 66.00000 205.000000
max 7940.00000 454037.000000
- 對price列的數據清洗
- 缺失值的處理:
我們先了解下這樣的判斷方法:
a={1:'a',2:'b'}
print([a[1]=='a'])
上述代碼打印結果必然是True,小括號([])相當於if判斷了,返回的值為布爾值。
下面對price為0的值(也就是缺失值)進行處理。
data['price'][(data['price']==0)]=None # 對price的缺失值統統賦值為None,方便下面處理
data['price'][(data['price']==0)]=64 # 也可以這樣寫,直接把price的缺失值設置為price的平均數64.那么下面的for循環設置price的缺失值就不需要寫。
對上面這段代碼拆分來看:
- (data['price']==0) 判斷data['price']列中哪行price的值等於0,等於的返回True,不等於返回False
- data['price'][(data['price']==0)] 這語句就是一下子把所有price=0的給取出來了 ,然后哪行的price等於0就 賦值為None
for i in data.columns: # 遍歷data的每列
for j in range(len(data)): # 遍歷data的每一行了。
if data[i].isnull()[j]: # i在這是一維(列),data[i]等於把這一列的值取出來了,j在這里是二維(行),i相當於XY軸的X軸,j相當於XY軸的Y軸,data[i].isnull是判斷整列的某一個值是nan那么就返回True,data[i].isnull[j]是逐行逐行的判斷是否為nan了,是的話返回True從而進行下面代碼塊的處理。
data[i][j]=64 # 缺失值設置為均值
- 異常值處理:
1.找到異常值:通過畫散點圖(橫軸:價格,縱軸:評論數)
我們這里的話要選取評論數,價錢。通常的方法就是說通過遍歷每一行的數據,取每一行中的price值,但是呢這個方法效率低下。
對此我們可以采用轉置方法,把price列轉置為一行,這樣就能夠快速取到這價錢的數據,還有評論數。
下面請看代碼:
dataT=data.T # 轉置下數據
prices = dataT.values[2] # 取第3行數據
comments = dataT.values[3] # 取第4行數據
pylab.plot(prices,comments,'o') # 畫散點圖
pylab.xlabel('prices')
pylab.ylabel('comments')
pylab.title(" The Good's price and comments")
pylab.show()
處理異常數據,我這里定義的異常數據就是評論數超過20W,價格大於2000,請看代碼:
line = len(data.values) # 取行數
col = len(data.values[0]) # 取列數
davalues = data.values #取data的所有值
for i in range(0,line): # 遍歷行數
for j in range(0,col): #遍歷列數
if davalues[i][3]>200000: #判斷評論數
#print('comments==i,j',i,j,davalues[i][j])
davalues[i][j] = 562 # 評論數取平均值
if davalues[i][2]>2000:
davalues[i][j] = 64 # 價錢取平均值
prices2=davalues.T[2]
comments2=davalues.T[3]
pylab.plot(prices2,comments2,'or')
pylab.xlabel('prices')
pylab.ylabel('comments')
pylab.title(" The Good's price and comments")
pylab.show()
此時,我們看圖:
顯然我們已經對評論數超過20W,價格大於2000的數據處理了,但是呢上圖顯示的還是不夠漂亮,因為異常點與正常點的差距太大了,導致正常點與正常點之間的間隔非常小,小到黏在一塊了,所以我們還需要在處理下,把評論數超過2000,價格大於300的處理掉,這樣的話,正常點就能夠很好的展現在圖上,代碼如下:
line = len(data.values) # 取行數
col = len(data.values[0]) # 取列數
davalues = data.values #取data的所有值
for i in range(0,line): # 遍歷行數
for j in range(0,col): #遍歷列數
if davalues[i][3]>2000: #判斷評論數,===主要修改這行
#print('comments==i,j',i,j,davalues[i][j])
davalues[i][j] = 562 # 評論數取平均值
if davalues[i][2]>300: # ====主要修改這行
davalues[i][j] = 64 # 價錢取平均值
prices2=davalues.T[2]
comments2=davalues.T[3]
pylab.plot(prices2,comments2,'or')
pylab.xlabel('prices')
pylab.ylabel('comments')
pylab.title(" The Good's price and comments")
pylab.show()
full example:
import pymysql
import numpy
import pandas
from matplotlib import pylab
#缺失值處理
#======
data['price'][(data['price']==0)]=64 # 對price的缺失值統統賦值為平均數
# 異常值處理:
# 1.找到異常值:通過畫散點圖(橫軸:價格,縱軸:評論數)
# 我們這里的話要選取評論數,價錢。通常的方法就是說通過遍歷每一行的數據,取每一行中的price值,但是呢這個方法效率低下,
# 對此我們可以采用轉置方法,把price列轉置為一行,這樣就能夠快速取到這價錢的數據,還有評論數
# 處理異常數據,我這里定義的異常數據就是評論數超過20W,價格大於2000
conn = pymysql.connect(host='192.168.56.4',user='root',passwd='123456',db='csdn',charset='utf8')
sql='select * from taob'
data = pandas.read_sql(sql,conn)
line = len(data.values) # 取行數
col = len(data.values[0]) # 取列數
davalues = data.values #取data的所有值
for i in range(0,line): # 遍歷行數
for j in range(0,col): #遍歷列數
if davalues[i][3]>2000: #判斷評論數
#print('comments==i,j',i,j,davalues[i][j])
davalues[i][j] = 562 # 評論數取平均值
if davalues[i][2]>300:
davalues[i][j] = 64 # 價錢取平均值
prices2=davalues.T[2]
comments2=davalues.T[3]
pylab.plot(prices2,comments2,'or')
pylab.xlabel('prices')
pylab.ylabel('comments')
pylab.title(" The Good's price and comments")
pylab.show()
生成的圖如下:
這張圖就很直觀的看出,價錢和評論數的關系了,價錢在100以內的,評論數也比較多,價錢越高,評論數相對來說越少。
數據集成與數據離散化
-
數據集成:不同來源的數據集合在一起,需要注意格式保持一致。
for example:
我這里有2個表數據,淘寶與京東的,淘寶的表就如上面所述的一樣,標題,url,價錢,評論,那么京東的下標為2的列也必須是價錢,只有數據格式保持一致,才能分析。 -
數據離散化:處理連續數據較好的方法。離散化就是指數據不集中,分散了。
for example:
一個班的考試成績就是從0-100分之間,這個數據是在100以內連續的,那么我們對這個數據分析的時候就可以這么做,把連續的數據或者近似連續的數據整合在一個點附近,比如0-60分為及格,60-80為良好.....
商品數據分布分析實戰
我們在這里要分析商品數據的分布,看評論數與價錢的在哪個數量段的分布最多。
首先我們需要計算出價錢和評論的最值,其次在計算最值之間的極差,最后計算組距(極差/組數,組數自己根據情況定義)。下面請看代碼:
# 數據分布:
# 1 求最值
# 2 計算極差
# 3 組距: 極差/組數
da2=davalues.T
# print('=======')
# print(data['price'])
pricemax = da2[2].max()
pricemin = da2[2].min()
commentmax = da2[3].max()
commentmin = da2[3].min()
# 極差
pricerg = pricemax - pricemin
commentrg = commentmax -commentmin
# 組距
pricedst = pricerg/10
commentdst = pricerg/10
# 繪制直方圖
# numpy.arrange(最小值,最大值,組距)
# 價錢直方圖
pricesty = numpy.arange(pricemin,pricemax,pricedst)
pylab.hist(da2[2],pricesty)
pylab.show()
# 評論直方圖
commentty = numpy.arange(commentmin,commentmax,commentdst)
pylab.hist(da2[3],pricesty)
pylab.show()
評論直方圖如下:
結論:
從上圖中我們可以看出,評論數最多的集中在100元以內的商品,評論數也間接的說明了購買數,因為購買后才能夠評論。
所以可以根據這個來直方圖來給商品定價。
價錢直方圖如下:
結論:
從上圖中我們可以看出,商品價錢最多的集中在50元以內的商品
code full example:
#!/usr/bin/env python
# __author__:Leo
import pymysql
import numpy
import pandas
from matplotlib import pylab
conn = pymysql.connect(host='192.168.56.4',user='root',passwd='123456',db='csdn',charset='utf8')
sql='select * from taob'
data = pandas.read_sql(sql,conn)
# 缺失值處理
data['price'][(data['price']==0)]=64 # 對price的缺失值統統賦值為price的平均數
# 異常值處理:
# 1.找到異常值:通過畫散點圖(橫軸:價格,縱軸:評論數)
# 我們這里的話要選取評論數,價錢。通常的方法就是說通過遍歷每一行的數據,取每一行中的price值,但是呢這個方法效率低下,
# 對此我們可以采用轉置方法,把price列轉置為一行,這樣就能夠快速取到這價錢的數據,還有評論數
line = len(data.values) # 取行數
col = len(data.values[0]) # 取列數
davalues = data.values #取data的所有值
for i in range(0,line): # 遍歷行數
for j in range(0,col): #遍歷列數
if davalues[i][3]>2000: #判斷評論數
#print('comments==i,j',i,j,davalues[i][j])
davalues[i][j] = 562 # 評論數取平均值
if davalues[i][2]>300:
davalues[i][j] = 64 # 價錢取平均值
prices2=davalues.T[2]
comments2=davalues.T[3]
pylab.plot(prices2,comments2,'or')
pylab.xlabel('prices')
pylab.ylabel('comments')
pylab.title(" The Good's price and comments")
pylab.show()
# 數據分布:
# 1 求最值
# 2 計算極差
# 3 組距: 極差/組數
da2=davalues.T
# print('=======')
# print(data['price'])
pricemax = da2[2].max()
pricemin = da2[2].min()
commentmax = da2[3].max()
commentmin = da2[3].min()
# 極差
pricerg = pricemax - pricemin
commentrg = commentmax -commentmin
# 組距
pricedst = pricerg/10
commentdst = pricerg/10
# 繪制直方圖
# numpy.arrange(最小值,最大值,組距)
# 價錢直方圖
pricesty = numpy.arange(pricemin,pricemax,pricedst)
pylab.hist(da2[2],pricesty)
pylab.show()
# 評論直方圖
commentty = numpy.arange(commentmin,commentmax,commentdst)
pylab.hist(da2[3],pricesty)
pylab.show()
好了,淘寶商城數據預處理實戰到此告一段落,下面我將繼續搞文本相似度匹配。