1. 程式人生 > 其它 >淘寶商ipad品資訊視覺化

淘寶商ipad品資訊視覺化

這是以前寫的記錄,我把它搬到部落格園上來。

紙上得來終覺淺,絕知此事要躬行,本文記錄如何使用Pandas、Matplotlib基礎知識對爬取的ipad資訊作視覺化,包括如下內容:

  • 價格分佈

  • 銷量對比

  • 店鋪銷量前20

  • 發貨地省份統計

 資料準備 :某寶ipad商品資訊(戳這裡檢視爬取過程)

 資料轉換    原始資料裡,價格和銷量資料型別不是整型或者浮點數,需要將其轉換格式後才能更好的定量分析,下面是我轉換後的資料。

因為有些商品沒有銷量,我在爬取的時候預設以“未知”填充,轉換後以NaN值替換“未知”,表示該商品銷量資料缺失。

 初步篩選   匯入Pandas庫,使用read_csv()方法讀取我們準備好的資料

  •  
data = pd.read_csv('data.csv',names=['origin','name',"price",'sale','shop'],index_col=["name"])  # 讀取資料

 刪除NaN    缺失資料不在分析範圍內,故將所有帶有NaN值的商品刪除(即每一行帶有NaN值都刪去)

  •  
data.dropna(axis=0,how="any")

 排序和再篩選   轉換,刪除NaN值後的資料還不能直接使用,注意分析的是ipad,但是表格裡充斥著許多的ipad配件商品,而且有些平板品牌也不是ipad(在此假定所有平板均為ipad),爬蟲無法區分哪些是平板,哪些是配件,一股腦全部爬取。在此我們劃定一個價格闕值=500,低於闕值即認為是配件,因為配件一般比主機便宜(純屬經驗劃分)

data = data[(data['price'] > 500)]   # 篩選價格超過500的資料price = data.price  #選取價格sale = data.sale    #選取銷量

現在我們已經拿到很純的價格和銷量資料了,關於如何在DataFrame裡統計特定數值的頻數,我還不清楚,不過可以曲線統計,Python列表資料提供有count()方法統計元素出現個數,只需將店鋪整列提取出來,轉換為列表,然後統計,排序後選取前20個。

# 統計值出現的次數def filter(lis):    count = {}    for i in lis:        count[i] = lis.count(i)
    return count  #返回型別為字典,省名為鍵,次數為值

另外商品發貨地格式並不統一,有些僅定位到省,有些則定位到地級市,需要將省份提取出來再進行統計,排序後,選取前七名,第七名以後的統計為"其他"。

origins = DataFrame({"origin":filter(origin)}).sort_values(axis=0,by="origin",ascending=False)  # 轉換為DataFrame型別,然後降序排序# 同樣地選取店鋪後統計出現次數,再轉換為DataFrame型別,排序後選取前20個shop = DataFrame({"count":filter(data.shop.values.tolist())}).sort_values(axis=0,by="count",ascending=False)['count'][:20]other = origins['origin'][7:].sum()  # 計算第七個後的發貨地次數總和,記為其他piedata = origins['origin'][:7].tolist() + [other]province_info = origins.index.tolist()[:7] + ['其他']

到此所有的資料都準備好,下一步使用Matplotlib繪製圖像


在繪製圖像之前,先來捋清楚什麼樣的資料該選擇什麼樣的資料圖來展示呢?

上述準備好的資料可以分為定性資料和定量資料,針對這兩種資料的展示互有差異,但又相輔相成。

定性資料:是一組表示事物性質、規定事物類別的文字表述型資料,如省份。

定量資料:指以數量形式存在著的屬性,並因此可以對其進行測量,以物理量為例,距離、質量、時間等都是定量資料。

 常用資料展示圖 :

  • 直方圖 適合比較不同物件間的數值差異

  • 餅圖  重點體現資料的型別和所佔整體的比例

  • 折線圖  重點體現資料的變化趨勢和未來走向,適合以時間為自變數的資料

  • 雷達圖  重點體現資料間不同維度之間的差異

  • 散點圖  考察兩個變數之間的關係

  • 風向玫瑰圖  反映一個物件的方向和頻率(個人感覺風向玫瑰圖和雷達圖表示型別相似)

  • 柱狀圖  對比不同類別資料間的差異

  • 箱型圖 適合展示一組資料的分散情況

  • 熱力圖 以特殊高亮的形式顯示訪客熱衷的頁面區域和訪客所在的地理區域的圖示

基於上述理解,我將使用直方圖展示價格分佈、用柱狀圖展示店鋪前20銷量、用氣泡圖展示價格和銷量之間的關係、用餅圖展示商品按省份歸類後的比值分佈。

先對圖做一個劃分,要在一張圖上展示四張子圖

大小相等子圖

我用subplots(2,2)方法劃分子圖區域,可以看到每一個子圖,其大小等同,如果想控制子圖大小,實現如下效果,推薦使用GridSpec類實現

大小不等同子圖

具體影象如何繪製(戳這裡回顧繪圖函式),僅展示程式碼,在繪圖過程中出現如下問題:

  • 預設刻度不美觀,如何自定義刻度

  • 餅圖圖例過大,遮擋餅圖展示

  • 新增圖例、標題、軸標籤後子圖互相遮掩

子圖部分遮掩,餅圖圖例過大,無次要刻度

以上問題解決方法:

  • 可通過如下方法設定主次要刻度

    ax.x/yaxis.set_major_locator(),ax.x/yaxis.set_minor_locator()

  • 餅圖圖例過大,可設定圖例字型調整

  • 修改配置引數

    rcParams.update({"figure.autolayout":True}),防止子圖互相遮掩

完整程式碼,重要語句都寫了註釋的

 
# -*- coding: utf-8 -*-
 
"""
 
@Date: 2021/3/25 23:01
 
@File: ipad_nanalysis.py
 
@Software: PyCharm
 
"""
 
import numpy as np
 
import matplotlib.pyplot as plt
 
import pandas as pd
 
from pandas import DataFrame,Series
 
from matplotlib import ticker ,rcParams
 
 
 
# 配置
 
rcParams.update({'figure.autolayout':True}) # 防止子圖出現重疊
 
rcParams['font.family']= "SimHei" # 設定中文字型
 
rcParams['axes.unicode_minus']=False # 座標軸顯示負號
 
 
 
# 清洗和篩選資料
 
data = pd.read_csv('data.csv',names=['origin','name',"price",'sale','shop'],index_col=["name"]).dropna(axis=0,how="any") # 讀取資料
 
data = data[(data['price'] > 500)] # 篩選價格超過500的資料
 
price = data.price #選取價格
 
sale = data.sale #選取銷量
 
 
 
origin = [i.split(" ")[0] for i in data.origin] # 篩選發貨地,有些發貨地格式為省份在前城市在後,如:廣東 深圳,但在此僅需省份
 
 
 
# 統計省份出現的次數
 
def filter(lis):
 
count = {}
 
for i in lis:
 
count[i] = lis.count(i)
 
return count #返回型別為字典,省份名為鍵,次數為值
 
 
 
origins = DataFrame({"origin":filter(origin)}).sort_values(axis=0,by="origin",ascending=False) # 轉換為DataFrame型別,然後降序排序
 
 
 
# 同樣地選取店鋪後統計出現次數,再轉換為DataFrame型別,排序後選取前20個
 
shop = DataFrame({"count":filter(data.shop.values.tolist())}).sort_values(axis=0,by="count",ascending=False)['count'][:20]
 
other = origins['origin'][7:].sum() # 計算第七個後的發貨地次數總和,記為其他
 
 
 
piedata = origins['origin'][:7].tolist() + [other]
 
province_info = origins.index.tolist()[:7] + ['其他']
 
# 氣泡圖
 
fig ,ax = plt.subplots(2,2,figsize=(20,10))
 
ax1,ax2,ax3,ax4 = ax[0][0],ax[0][1],ax[1][0],ax[1][1]
 
ax1.scatter(x=price,y=sale,s=sale * 0.08,c=np.random.randint(0,1000,(len(sale),)),label="商品銷量",)
 
# 設定y軸限度
 
ax1.set_ylim(-500,max(sale) + 1000)
 
# 設定xy軸的主要,次要刻度
 
ax1.xaxis.set_major_locator(ticker.MultipleLocator(1000))
 
ax1.yaxis.set_major_locator(ticker.MultipleLocator(1000))
 
ax1.xaxis.set_minor_locator(ticker.MultipleLocator(100))
 
# 新增圖例,標題,軸標籤
 
ax1.legend(fontsize=8,shadow=True,frameon=True,markerscale=0.5)
 
ax1.set_title("ipad產品銷量氣泡圖",pad=5,fontsize=15)
 
ax1.set_xlabel("價格",fontsize=10,labelpad=10)
 
ax1.set_ylabel("銷量",rotation=0,labelpad=10,loc="top")
 
 
 
# 直方圖
 
ax2.hist(price,bins=50,width=150)
 
ax2.xaxis.set_major_locator(ticker.MultipleLocator(500))
 
ax2.set_xlabel("價格",fontsize=10,labelpad=5)
 
ax2.set_ylabel("數量",rotation=0,labelpad=10,loc="top")
 
ax2.set_title("ipad產品價格分佈直方圖",fontsize=15,pad=5,fontweight="bold")
 
ax2.yaxis.set_minor_locator(ticker.MultipleLocator(5))
 
ax2.xaxis.set_minor_locator(ticker.MultipleLocator(100))
 
ticklabel = ax2.xaxis.get_ticklabels()
 
plt.setp(ticklabel,fontsize=10,rotation=45)
 
ax2.grid(alpha=0.3,linewidth=0.5,which="both") #新增網格
 
 
 
# 餅圖
 
ax4.pie(piedata,labels=province_info,explode=[0,0.05,0.1,0.2,0.3,0.4,0.5,0.7],autopct="%.1f%%",pctdistance=0.8,textprops={'fontsize':10},)
 
ax4.legend(loc="best",ncol=2,fontsize=6)
 
ax4.set_title("ipad發貨地餅狀圖",fontsize=15)
 
 
 
 
 
# 條形圖
 
ax3.barh(shop.index,width=shop.values,color="red")
 
# 設定次要刻度
 
ax3.xaxis.set_minor_locator(ticker.MultipleLocator(5))
 
ax3.grid(axis='x',which="both",alpha=0.3)
 
ax3.set_title("店鋪銷量前20條形圖",fontsize=15,pad=5)
 
ax3.set_xlabel("銷量",fontsize=12,labelpad=5)
 
 
 
 
 
#plt.savefig("taobao_info.png",dpi=500)
 
plt.show()
 

  

相關資料僅作學習用,侵權請聯絡