數據分析之數據可視化

數據可視化是數據分析的重要內容。通過使用大量的數據集構成數據圖像,同時將數據的各個屬性值以多維數據的形式表示,可以從不同的維度觀察數據,從而對數據進行更深入的觀察和分析。

python上用於數據分析的庫主要有matplotlibseaborn

matplotlib的使用

使用matplotlib首先要安裝相應的庫,可以使用

pip安裝,或者安裝集成環境Anaconda後,採用conda命令安裝

以下是matplotlib的基本應用

構建直方圖:

import matplotlib.pyplot as plt #導入指定的pyplot庫後重命名為pltx = [1, 2, 3, 4]y = [3, 5, 7, 9]plt.plot(x, y) #使用plot繪製線條plt.show() #顯示圖像

美化圖形:

plt.plot(x, y, color=r, marker=o, linestyle=dashed) # 指定顏色為紅色,值o為圓圈標記,指定線段樣式(linestyle)為虛線plt.axis([0, 10, 0, 5]) #分別指定x坐標軸、y坐標軸的取值範圍plt.show()

搭配numpy:

import numpy as np #導入numpy包,重命名為npx = np.arange(1, 10, 0.5) #使用numpy生成數組,間隔為0.5y = np.arange(1, 19) plt.plot(x, y)plt.show()

繪製多個線性:

y1 = yy2 = x**2y3 = x**3lineList = plt.plot(x,y1, x, y2, x, y3)plt.setp(lineList, color=r)plt.show()print(數據類型:, type(lineList))print(數據長度:, len(lineList))

圖上添加文本:

#指定默認字體 plt.rcParams[font.sans-serif] = [SimHei] #解決負號-顯示為方塊的問題 plt.rcParams[axes.unicode_minus] = False plt.plot(x, y)plt.xlabel(x坐標軸)plt.ylabel(y坐標軸)添加註釋:參數名xy:箭頭注釋中箭頭所在位置,參數名xytext:注釋文本所在位置,arrowprops在xy和xytext之間繪製箭頭,shrink表示注釋點與注釋文本之間的圖標距離plt.annotate(我是注釋, xy=(2,5), xytext=(2, 6), arrowprops=dict(facecolor=black, shrink=0.01),)plt.title(標題)plt.show()

多圖繪畫

fig = plt.figure() #創建畫板ax1 = plt.subplot(2,1,1) #創建子畫,生成一個2行1列的子圖矩陣,當前是第一個子圖plt.plot([2,3,4])ax2 = plt.subplot(2,1,2)#創建子畫,生成一個2行1列的子圖矩陣,當前是第二個子圖plt.plot([5,6,7])plt.show()

如果沒有指明畫板figure()和子圖subplot,會默認創建一個畫板figure(1) 和一個子圖subplot(111)

數據可視化實戰

股票數據分析

獲取數據

from pandas_datareader import data #導入獲取數據包import fix_yahoo_finance as yfyf.pdr_override() #修復獲取數據錯誤的問題start_date = 2017-01-01 #指定獲取時間end_date = 2018-01-01gafataDict={谷歌:GOOG,亞馬遜:AMZN,Facebook:FB, 蘋果:AAPL,阿里巴巴:BABA,騰訊:0700.hk} #字典:6家公司的股票#獲取阿里巴巴股票數據babaDf = data.get_data_yahoo(gafataDict[阿里巴巴], start_date, end_date)#獲取谷歌股票數據googDf=data.get_data_yahoo(gafataDict[谷歌],start_date, end_date)#獲取亞馬遜股票數據amazDf=data.get_data_yahoo(gafataDict[亞馬遜],start_date, end_date)#獲取Facebook股票數據fbDf=data.get_data_yahoo(gafataDict[Facebook],start_date, end_date)#獲取蘋果股票數據applDf=data.get_data_yahoo(gafataDict[蘋果],start_date, end_date)#獲取騰訊股票數據txDf=data.get_data_yahoo(gafataDict[騰訊],start_date, end_date)#騰訊是港股,所以收盤價是港幣,按照今天的匯率將其轉化為美元exchange=0.1278 #港幣兌換美元的匯率,這個值可以根據在網上查到當天的最新匯率#為了方便後期多家公司的股價比較,增加新的一列收盤價(美元)txDf[Close_dollar]= txDf[Close]* exchange

數據可視化

股票走勢比較:

import matplotlib.pyplot as plt#指定默認字體 plt.rcParams[font.sans-serif] = [SimHei]#解決負號-顯示為方塊的問題 plt.rcParams[axes.unicode_minus] = False ax1 = googDf.plot(x=googDf.index, y=Close,label=谷歌) #在同一張畫紙上畫amazDf.plot(ax=ax1, x=amazDf.index, y=Close,label=亞馬遜)applDf.plot(ax=ax1,x=applDf.index,y=Close,label=蘋果)babaDf.plot(ax=ax1,x=babaDf.index,y=Close,label=阿里巴巴)txDf.plot(ax=ax1,x=txDf.index,y=Close_dollar,label=騰訊)# 添加文本信息plt.xlabel(時間)plt.ylabel(股價(美元))plt.title(2017年GAFATA股價走勢比較)#顯示網格plt.grid(True)plt.show()

散點圖:成交量和股價:

babaDf.plot(x=Vloume, y=Close, kind=scatter)#參數叫kind這個值表示繪製圖形的類型,這裡的值等於scatter表示繪製散點圖。plt.xlabel(成交量)plt.ylable(股價(美元))plt.title(成交量和股價)plt.grid(True)plt.show()

六家公司股票的平均值:

gafataMeanList=[googDf[Close].mean(),#谷歌 amazDf[Close].mean(),#亞馬遜 fbDf[Close].mean(),#Facebook applDf[Close].mean(),#蘋果 babaDf[Close].mean(),#阿里巴巴 txDf[Close_dollar].mean()#騰訊 ]#創建pandas一維數組SeriesgafataMeanSer=pd.Series(gafataMeanList, index=[谷歌, 亞馬遜, Facebook, 蘋果, 阿里巴巴, 騰訊])gafataMeanSer.plot(kind=bar,label=GAFATA) #kind指定柱狀圖#圖片標題plt.title(2017年GAFATA股價平均值)#x坐標軸文本plt.xlabel(公司名稱)#y坐標軸文本plt.ylabel(股價平均值(美元))plt.grid(True)plt.show()

分析結果:可以看出,僅從股票價格上來判斷,亞馬遜和谷歌的股票價格要遠遠的超過了其他四家。但是這裡只是算的平均值,下面我們看下用四分位數繪製的箱線圖

箱線圖:

#存放6家公司的收盤價closeDf=pd.DataFrame()#合併6家公司的收盤價closeDf=pd.concat([closeDf,googDf[Close],#谷歌 amazDf[Close],#亞馬遜 fbDf[Close],#Facebook applDf[Close],#蘋果 babaDf[Close],#阿里巴巴 txDf[Close_dollar]#騰訊 ],axis=1)#重命名列名為公司名稱closeDf.columns=[谷歌,亞馬遜,Facebook,蘋果,阿里巴巴,騰訊]#箱線圖closeDf.plot(kind=box)plt.grid(True)plt.show()

kaggle電影項目數據分析

一、提出問題

分析imdb的電影數據,找出潛在的數據聯繫,獲得有價值的信息。

二、理解數據

導入數據

import numpy as npimport pandas as pdimport matplotlib.pyplot as pltmovies_file = tmdb_5000_movies.csvcredits_file = tmdb_5000_credits.csvmovies = pd.read_csv(movies_file, encoding=utf-8) #指定編碼集為utf8,防止轉換為json時報錯credits = pd.read_csv(credits_file)#列印行列數print(credits:,credits.shape,movies:,movies.shape)movies_credits = pd.merge(movies, credits, left_on=id, right_on=movie_id, how=outer) # 不用concat的原因,有可能是兩張表的id並不是一一對應的movies_credits.head()#列印行列數print(movies_credits:,movies_credits.shape)

分析數據,刪除重複的數據

del movies_credits[movie_id]del movies_credits[title_y]data = movies_credits

查看數據集信息

# 整體查看數據情況,數據類型和,數據缺失情況data.info()

輸出結果為:

<class pandas.core.frame.DataFrame>Int64Index: 4803 entries, 0 to 4802Data columns (total 22 columns):budget 4803 non-null int64 預算genres 4803 non-null object 風格列表,按 | 分隔,最多 5 種風格homepage 1712 non-null object 主頁id 4803 non-null int64 id號keywords 4803 non-null object 與電影相關的關鍵字,按 | 分隔,最多 5 個關鍵字original_language 4803 non-null object 電影語言original_title 4803 non-null object 電影名稱overview 4800 non-null object 劇情摘要popularity 4803 non-null float64 在 Movie Database 上的相對頁面查看次數production_companies 4803 non-null object 製作公司列表,按 | 分隔,最多 5 家公司production_countries 4803 non-null object 製作國家release_date 4802 non-null object 首次上映日期revenue 4803 non-null int64 收入runtime 4801 non-null float64 電影時長spoken_languages 4803 non-null object 對白語言status 4803 non-null object 狀態tagline 3959 non-null object 標語title_x 4803 non-null object 電影名稱vote_average 4803 non-null float64 平均評分vote_count 4803 non-null int64 評分次數cast 4803 non-null object 演員列表,按 | 分隔,最多 5 名演員crew 4803 non-null object 職員表dtypes: float64(3), int64(4), object(15)memory usage: 863.0+ KB

我們發現數據總共4803行,其中數據類型列電影時長(runtime)有缺失數據,缺失2條數據;

字元串類型缺失數據的列有:主頁(homepage)劇情摘要(overview)首次上映日期(release_date)標語(tagline) .

其中,主頁缺失最多,缺失率為:

frac{3091}{4803} = 64.35\%

之後進入數據清洗

三、數據清洗

缺失值處理

#runtime缺失兩條數據,採用平均數填充data[runtime] = data[runtime].fillna(data[runtime].mean())#由於缺失數據較多,主頁(homepage)缺失值填充為U,表示未知(Unknow)data[homepage] = data[homepage].fillna(U)#由於劇情摘要和標語無法得出,故設置為未知data[overview] = data[overview].fillna(U)data[tagline] = data[tagline].fillna(U)#上映日期缺失一條,查詢到缺失的電影data.loc[data[release_date].isnull(), title_x]

查詢結果為:

4553 America Is Still the Place

Name: title_x, dtype: object

#上網查到到缺失電影首次上映日期為2014-06-01,填充缺失值data[release_date]=data[release_date].fillna(2014-06-01)

數據類型轉換

時間轉換:

data[release_date] = pd.to_datetime(data[release_date], format=%Y-%m-%d)#提取年份,便於進一步分析data[release_year] = data[release_date].dt.year

由於數據中有json格式,要轉換為字元串,便於進行下一步分析:

import jsondef json2str(x): a = [] for i in x: a.append(i[name]) return ,.join(a)#genres 風格種類data[genres]=data[genres].apply(json.loads)data[genres]=data[genres].apply(json2str)# production_companies 製作公司data[production_companies]=data[production_companies].apply(json.loads)data[production_companies]=data[production_companies].apply(json2str)# keywords 與電影相關的關鍵字data[keywords]=data[keywords].apply(json.loads)data[keywords]=data[keywords].apply(json2str)# spoken_languages 對白語言data[spoken_languages]=data[spoken_languages].apply(json.loads)data[spoken_languages]=data[spoken_languages].apply(json2str)data[spoken_languages].head()# cast 主演data[cast]=data[cast].apply(json.loads)data[cast]=data[cast].apply(json2str)

四、問題分析

關鍵詞分析

keywordsList = dict() #定義字典,用於儲存關鍵詞for get_str in data[keywords]: get_dict = json.loads(get_str) #將字元串解析為字典 for get_keywords in get_dict: get_name = get_keywords[name] #獲取關鍵字 if get_name not in keywordsList.keys(): keywordsList[get_name] = 1 #如果之前沒有收錄該關鍵詞,加入字典中 keywordsList[get_name] = keywordsList[get_name] + 1 #如果之前收錄過,直接+1keyword_occurences = [] #定義列表,用於排序for k,v in keywordsList.items(): keyword_occurences.append([k,v]) #將字典轉為列表keyword_occurences.sort(key = lambda x:x[1], reverse = True) #進行排序# print(keyword_occurences)#畫出圖像plt.rcParams[font.sans-serif] = [SimHei] #解決負號-顯示為方塊的問題 plt.rcParams[axes.unicode_minus] = False fig = plt.figure(1, figsize=(18,13)) #定義畫板words = dict() trunc_occurences = keyword_occurences[0:50] #提取前50個關鍵詞for s in trunc_occurences: words[s[0]] = s[1] #轉換為字典tone = 55.0 # define the color of the wordsax2 = fig.add_subplot(2,1,2) #添加子畫y_axis = [i[1] for i in trunc_occurences]x_axis = [k for k,i in enumerate(trunc_occurences)]x_label = [i[0] for i in trunc_occurences]plt.xticks(rotation=85, fontsize = 15)plt.yticks(fontsize = 15) #定義文字大小plt.xticks(x_axis, x_label)plt.ylabel("出現次數", fontsize = 18, labelpad = 10)ax2.bar(x_axis, y_axis, align = center, color=g)plt.title("關鍵詞分布",bbox={facecolor:k, pad:5},color=w,fontsize = 25)plt.show()

分析:可以看出最吸引人眼球的關鍵詞是女性導演獨立電影

電影發展分析

# 電影發展data[decade] = data[release_year].apply(lambda x:((x-1900)//10)*10)# 通過函數獲取輸入數據的各種描述統計學信息def get_stats(gr): return {min:gr.min(),max:gr.max(),count: gr.count(),mean:gr.mean()}# 創建一個dataframe對象用於儲存信息:test = data[release_year].groupby(data[decade]).apply(get_stats).unstack()sns.set_context("poster", font_scale=0.85)# 設置標籤def label(s): val = (1900 + s, s)[s < 100] chaine = if s < 50 else "{}s".format(int(val)) return chaineplt.rc(font, weight=bold)f, ax = plt.subplots(figsize=(11, 6))labels = [label(s) for s in test.index]sizes = test[count].valuesexplode = [0.2 if sizes[i] < 100 else 0.01 for i in range(11)]ax.pie(sizes, explode = explode, labels=labels, autopct = lambda x:{:1.0f}%.format(x) if x > 1 else , shadow=False, startangle=0)ax.axis(equal)ax.set_title(每10年發布電影數所佔比例, bbox={facecolor:k, pad:5},color=w, fontsize=16);data.drop(decade, axis=1, inplace = True)plt.show()

分析:電影產業快速發展,直到2010年代,基本每年電影發布數都成倍速增長。到了2010年代,可能由於經濟危機的緣故,導致電影數量下降。

電影類型數量分析

# 電影類型分析genres_labels = set() #定義集合保存電影類型for s in data[genres].str.split(,).values: genres_labels = genres_labels.union(set(s)) #合併集合#計算數量genres_count = {}for d in data[genres]: l = d.split(,) for i in l: if i not in genres_count.keys(): genres_count[i] = 1 genres_count[i] = genres_count[i] + 1#進行排序genres_occurences = [] #定義列表,用於排序for k,v in genres_count.items(): genres_occurences.append([k,v]) #將字典轉為列表genres_occurences.sort(key = lambda x:x[1], reverse = True) #進行排序genres_occurences = genres_occurences[:10]#數據可視化#數量最多的10大類型電影genres_occurences = dict(genres_occurences)genres_occurences = pd.DataFrame([genres_occurences]) #字典轉為dataframegenres_occurences.plot(kind=barh,figsize=(8,5),width=0.8) #barh橫向柱狀圖更易比較大小plt.title(各電影類型的數量對比,fontsize=18)plt.xlabel(數量,fontsize=15)plt.grid(True)plt.show()

電影類型隨時間變化

#將電影類型添加到列,需進行one-hot編碼genresDf=pd.DataFrame()for genre in genres_occurences.keys(): genresDf[genre]=data[genres].str.contains(genre).apply(lambda x:1 if x else 0)#用年份索引genresDf[release_year]=data[release_year]genresDf.index=data[release_year]genresDf=genresDf.sort_index() #按數據框行索引進行排序#對每個類型的電影按年份求和genresDf=genresDf.groupby(release_year).sum() #groupby函數對數據集進行聚類運算 genresDf.plot(figsize=(8,5))plt.title(電影類型隨時間變化)plt.xlabel(時間)plt.ylabel(數量)plt.grid(True)plt.show()

從上圖可以看出,所有類型的電影從1960-1990開始緩慢增長,此後呈現急劇增長,其中戲劇(Drama)增長最快,數量最多,喜劇(Comedy)次之,而科幻小說類電影數量最少,最近幾年,恐怖片(Thriller)數量超過喜劇,而動作片(Action)接近恐怖片。反映了人們對電影類型需求的變化。

影響電影收入分析

#電影收入的相關矩陣corrDf=data.corr()corrDf[revenue].sort_values(ascending=False) #相關程度按降序排列

輸出為:

revenue 1.000000vote_count 0.781487budget 0.730823popularity 0.644724runtime 0.251080vote_average 0.197150release_year 0.090084id -0.050425Name: revenue, dtype: float64

電影收入與評分次數的關係

#電影收入與評分次數的關係sns.regplot(data[vote_count],data[revenue]) #seaborn中regplot函數用於繪製雙變數線性回歸曲線plt.title(電影收入與評分次數的關係)plt.xlabel(預算)plt.ylabel(收益)plt.grid(True)plt.show()

分析:可以看出,電影收入與評分次數、預算、電影頁面相對查看次數的相關性較高。

電影收入和評分次數的相關性曲線是正線性相關,可以是因為觀看電影的人數越多,進行評價的人就越多。

五、總結

以上是對數據的簡單分析和可視化,通過分析,可得到電影的發展趨勢,以及電影收入相關因素,便於以後在電影行業進行相關投資等。隨著學習的深入,以後會繼續補充相關內容。

參考資料

數據可視化-電影數據分析

Film recommendation engine


推薦閱讀:

在節點-鏈接圖中巧用坐標變換畫線
智慧城市案例分享
爬蟲與反爬蟲 | 土法破解字元映射反爬策略及高頻詞可視化
聽說你想做一份高級的可視化圖表?

TAG:數據挖掘 | 數據可視化 | 數據分析 |