在處理數(shù)據(jù)的過程中笛丙,經常用到強大的Pandas.DataFrame宋税,由于其參數(shù)多自由度高,有時候容易暈頭轉向一睁。
故將數(shù)據(jù)清洗宗苍、處理和畫圖中的常用操作總結如下稼稿。
不定期更新,歡迎收藏讳窟。
這次利用tushare提供的影院日度票房數(shù)據(jù)接口為例進行演示让歼。
為什么要放王校長吃熱狗的圖?答案在文中丽啡。
(1)準備工作
加載需要的庫:
# -*- coding: UTF-8 -*-
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import tushare as ts
from datetime import datetime
import time
import pylab
注冊tushare獲得‘your token’:
%matplotlib inline
pro = ts.pro_api('your token')
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False
df = pd.DataFrame()
設定jupyter notebook中顯示圖片的尺寸:
pylab.rcParams['figure.figsize'] = (8, 4.5)
(2)獲取數(shù)據(jù)
def get_data(df, startdate, enddate):
# 日期格式轉換
tp = [x.strftime('%Y%m%d') for x in list(pd.date_range(start=startdate, end=enddate))]
print(tp)
for t in tp:
#加個延遲避免被ban
time.sleep(62/40)
dfdaily = pro.bo_cinema(date = t)
df = pd.concat([df, dfdaily], axis=0) # 縱向合并
return df
startdate = '20190205'
enddate = '20190321'
data = get_data(df, startdate, enddate)
輸出的日期列表:
['20190205', '20190206', '20190207', '20190208', '20190209', '20190210', '20190211', '20190212', '20190213', '20190214', '20190215', '20190216', '20190217', '20190218', '20190219', '20190220', '20190221', '20190222', '20190223', '20190224', '20190225', '20190226', '20190227', '20190228', '20190301', '20190302', '20190303', '20190304', '20190305', '20190306', '20190307', '20190308', '20190309', '20190310', '20190311', '20190312', '20190313', '20190314', '20190315', '20190316', '20190317', '20190318', '20190319', '20190320', '20190321']
查看原始數(shù)據(jù)前5行:
data.head()
說明:該數(shù)據(jù)是按每日票房收入(day_amount)對全國影院進行排名谋右,列出全國排名前100的影院(看看有你去過的沒)。
查看data的形狀:
data.shape
(3900, 9)
描述性統(tǒng)計:
data.describe().T
(3)進行初步分析
按影院上榜次數(shù)計數(shù):
c_name_conunts = data['c_name'].value_counts()
c_name_conunts[:30]
輸出前30家:
(看看有你去過的嗎~)
金逸北京薈聚IMAX店 39
廣州飛揚影城(正佳分店) 39
首都電影院西單店 39
武漢漢街萬達廣場店 39
UME影城(北京雙井店) 39
蘭州城關萬達廣場店 39
武商摩爾國際電影城 39
中影國際影城珠海華發(fā)2店 39
Jackie Chan北京耀萊 39
南京新街口國際影城 38
金逸北京大悅城IMAX店 38
蘭州中心空間站IMAX影城 38
北京通州萬達廣場店 37
北京市金泉港國際影城 37
廣州市捷登都會飛揚影城 36
金逸天津大悅城IMAX店 36
成都錦華萬達廣場店 36
南昌紅谷灘萬達廣場店 35
昆明萬達影城同德廣場店 35
廣州飛揚影城 35
首都電影院昌平店 35
深圳市百老匯電影中心影城 34
盧米埃北京長楹天街IMAX影城 34
金逸上海龍之夢IMAX店 33
大連經開萬達廣場店 33
金逸廣州海珠城IMAX店 33
中影國際影城北京昌平永旺店 33
中影國際影城武漢光谷天河店 32
福州倉山萬達廣場店 32
UME影城(重慶渝中店) 31
Name: c_name, dtype: int64
畫簡單的橫柱狀圖:
c_name_conunts[:15].plot(kind='barh', rot=0)
按影院名稱是否含“萬達”進行分類补箍,研究萬達相關影院的情況:
(強行解釋題圖)
if_wanda = np.where(data.c_name.str.contains('萬達'), 'Wanda', 'Not Wanda')
if_wanda[:5]
查看:
array(['Not Wanda', 'Not Wanda', 'Not Wanda', 'Wanda', 'Not Wanda'], dtype='<U9')
想要直接按萬達和非萬達分組進行與上面類似的計數(shù)會有些復雜改执,這里提供pandas之父麥金尼的方法啸蜜,創(chuàng)造性的用df.groupby()和.size().unstack()解決:
by_cname_ifwanda = data.groupby(['rank', if_wanda])
agg_counts = by_cname_ifwanda.size().unstack().fillna(0)
agg_counts[:10]
效果如下:
在萬達的電影院,每日排名一般在多少位呢辈挂?
畫出能體現(xiàn)萬達比例的柱形圖衬横,可視性更好:
agg_counts[:25].plot(kind='barh', stacked=True)
畫折線圖:
plt.plot(agg_counts['Not Wanda'], label='Not Wanda', linestyle='--')
plt.plot(agg_counts.Wanda, label='Wanda')
plt.plot((0, 100), (18.5, 18.5), color='black', lw =0.5)
plt.legend()
(4)用透視表分析
將if_wanda添加到原始數(shù)據(jù)中形成新的列(即df增加columns),并查看:
data['ifwanda'] = if_wanda
data.head()
考察同樣排名情況下呢岗,萬達與非萬達的平均票價差距:
mean_stat = data.pivot_table('avg_price', index='rank', columns='ifwanda', aggfunc='mean')
mean_stat['diff']=mean_stat['Wanda']-mean_stat['Not Wanda']
mean_stat[:20].round(2)
畫柱狀圖:
#plt.plot(mean_stat['diff'])
plt.plot((0, 100), (0, 0), color='black', lw =0.5)
plt.bar(mean_stat.index, mean_stat['diff'])
直觀上冕香,排名相同的情況下,萬達的影院要比非萬達影院平均票價貴后豫。
求平均票價差距的均值:
mean_stat['diff'].mean()
3.4035306779919057
即平均貴3.40元悉尾。
接下來,從總體角度分析挫酿。
創(chuàng)建一個新的數(shù)據(jù)集构眯,只保留想研究的3個columns:
(通過字典創(chuàng)建)
sum_datadic = {'date': data.date,
'day_amount': data.day_amount,
'att_ratio': data.att_ratio,
'avg_price': data.avg_price}
sum_data = pd.DataFrame(sum_datadic)
sum_data[:10]
日常中面板數(shù)據(jù)比較常用的,按日期求均值:
(注意pivot_table的用法)
mean2 = data.pivot_table(['att_ratio', 'day_amount', 'avg_price'], index='date', aggfunc='mean')
mean2.day_amount = mean2.day_amount/10000
mean2[:10].round(2)
研究新數(shù)據(jù)集3列間的關系早龟,
畫折線圖:
timeline = [datetime.strptime(d, '%Y%m%d').date() for d in mean2.index]
plt.plot(timeline, mean2.att_ratio, label='日均上座率(%)', linestyle=':')
plt.plot(timeline, mean2.day_amount, label='日均單影院收入(萬元)',linestyle='--')
plt.plot(timeline, mean2.avg_price, label='日均票價(元)')
plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%m-%d'))
plt.legend(loc='best')
plt.grid()
另一種方法:直接對原始數(shù)據(jù)按日平均
data_by_day = data.pivot_table(data.columns, index='date', aggfunc='mean')
data_by_day.round(2)[:10]
結果發(fā)現(xiàn)少了一行(aud_count)芝加,原因是該列數(shù)據(jù)的類型不是整數(shù)型或浮點型硅卢,不能計算。
類型轉換就可以了:
data.aud_count = data.aud_count.astype('int')
data_by_day = data.pivot_table(data.columns, index='date', aggfunc='mean')
data_by_day.round(2)[:10]
將data_by_day中的6列數(shù)據(jù)用折線圖表示出來藏杖,
畫多個子圖:
fig, axs = plt.subplots(6, 1)
j=0
timeline = [datetime.strptime(d, '%Y%m%d').date() for d in data_by_day.index]
for col in data_by_day.columns:
axs[j].plot(timeline, data_by_day[col])
axs[j].xaxis.set_major_formatter(mdates.DateFormatter('%m%d'))
#axs[j].xaxis.set_major_locator(mdates.MonthLocator())
axs[j].set(title=col)
axs[j].grid()
j += 1
plt.tight_layout()
#plt.gcf().autofmt_xdate()
發(fā)現(xiàn)圖像在jupyter notebook里顯示的太過細小了将塑,通過下面的語句調整顯示圖片的尺寸;
pylab.rcParams['figure.figsize'] = (8, 16)
重新畫圖:
fig, axs = plt.subplots(6, 1)
j=0
timeline = [datetime.strptime(d, '%Y%m%d').date() for d in data_by_day.index]
for col in data_by_day.columns:
axs[j].plot(timeline, data_by_day[col])
axs[j].xaxis.set_major_formatter(mdates.DateFormatter('%m%d'))
#axs[j].xaxis.set_major_locator(mdates.MonthLocator())
axs[j].set(title=col)
axs[j].grid()
j += 1
plt.tight_layout()
#plt.gcf().autofmt_xdate()
(本文基于偉大的麥金尼所著《利用python進行數(shù)據(jù)分析》和本人粗淺的日常經驗蝌麸。)