Part 1: 你真的認(rèn)識大數(shù)據(jù)嗎吟逝?
我周圍很多人,開口閉口都是云計算君旦、大數(shù)據(jù)澎办。你要是真的去追究什么事大數(shù)據(jù)嘲碱,什么級別的數(shù)據(jù)才叫做大金砍,那么他們多半是答不上來的局蚀。我見過好幾個人,處理過的最大數(shù)據(jù)不過是幾百M(fèi)的csv文件恕稠,卻整天在談hadoop,spark之類的琅绅。這簡直是拿大炮去打蚊子,真是浪費(fèi)了材料鹅巍。以我的實(shí)踐經(jīng)驗來看千扶,低于500G,甚至1TB的數(shù)據(jù)都是可以通過pandas這個數(shù)據(jù)利器來解決骆捧,最多加上dask這個利器澎羞。所以當(dāng)你的數(shù)據(jù)只有幾百M(fèi),幾個G,或者幾十個G的時候敛苇,就用你手頭的單機(jī)電腦去完成它吧妆绞。
Part 2: 問題描述
我們手里面有一個差不多100G的亞馬遜用戶在購買商品后留下的評論數(shù)據(jù)(數(shù)據(jù)格式為json)。我們需要統(tǒng)計這100G數(shù)據(jù)中枫攀,出現(xiàn)頻率最高的100個詞語括饶。然后制作一個詞云表現(xiàn)表現(xiàn)出來,所謂的詞云来涨,就是類似于這樣的一張圖片图焰,顯然還是圖片讓我們對單詞出現(xiàn)的熱度一目了然。
Part 3: 問題難點(diǎn)
- 數(shù)據(jù)量太大蹦掐,而我的電腦內(nèi)存只有32G技羔,無法將數(shù)據(jù)一次性裝入內(nèi)存。需要我們隊數(shù)據(jù)進(jìn)行分塊處理卧抗。在解決問題之前堕阔,我們需要對要處理的數(shù)據(jù)一探究竟。我的數(shù)據(jù)來源是公開的颗味,由MIT一位教授放在亞馬遜用戶評論數(shù)據(jù)超陆,只需要給他發(fā)一個郵件,說一下自己的意圖浦马,就可以直接下載了时呀。下面我結(jié)合著代碼,介紹整個項目的流程晶默。
import dask.bag as db
import ujson as json #聽說用ujson解析比普通json快好幾倍哦
import pandas as pd
import numpy as np
import gzip #解析gzip等壓縮文件
import re
b = db.from_filenames(r'E:\研究生階段課程作業(yè)\python\zhihu_bigdata\complete.json.gz',encoding='utf-8').map(json.loads)
b.take(1) #檢查數(shù)據(jù)的格式
>>out[1]:'asin': 'B003UYU16G',
'helpful': [0, 0],
'overall': 5.0,
'reviewText': "It is and does exactly what the description said it would be and would do. Couldn't be happier with it.",
'reviewTime': '11 21, 2012',
'reviewerID': 'A00000262KYZUE4J55XGL',
'reviewerName': 'Steven N Elich',
'summary': "Does what it's supposed to do",
'unixReviewTime': 1353456000}
在這段代碼中谨娜,我們首先讀取complete.json.gz里面的數(shù)據(jù),這里我用到了dask里面的bag類型磺陡,dask會根據(jù)你的內(nèi)存情況來適當(dāng)讀取不超過內(nèi)存大小的數(shù)據(jù)趴梢,在這里我建議如果你對神馬spark漠畜,hadoop之類的不感興趣,又想搞一些大數(shù)據(jù)方面的行當(dāng)(不超過1TB)坞靶,那么我還是建議你好好看一下dask憔狞。
因為我們只對里面的 "reviewText"字段感興趣,我們對其他的字段直接忽略彰阴。在提取" "reviewText"數(shù)據(jù)之前瘾敢,我們看一下需要處理多少行這樣的數(shù)據(jù)。
print(sum([1 for _ in gzip.open(r'E:\研究生階段課程作業(yè)\python\zhihu_bigdata\complete.json.gz')])) #計算用戶的評論數(shù)目
out[2]:143674325 #差不多1.5億行數(shù)據(jù)尿这,在我電腦上跑了差不多三分鐘
沒錯簇抵,只有一行數(shù)據(jù),不用把數(shù)據(jù)全部裝入內(nèi)存射众,我們就可以計算這100G數(shù)據(jù)碟摆,究竟有多少個類似于out[1]這樣的數(shù)據(jù)段。你問我為什么喜歡python叨橱,這就是理由典蜕,因為他強(qiáng)大,簡潔雏逾,優(yōu)雅嘉裤,代碼可讀性好。
我們需要處理的數(shù)據(jù)差不多有100G栖博,遠(yuǎn)超我們的內(nèi)存極限屑宠。
采用的步驟如下:
step 1:對每一個用戶數(shù)據(jù),轉(zhuǎn)化成字典結(jié)構(gòu)仇让。
step 2: 提取里面的 reviewText
step 3: 使用分詞典奉,把句子轉(zhuǎn)化成單詞
step 4:對每個單詞進(jìn)行hash,對于相同的hash值,寫進(jìn)txt文件
step 5: 對于同一個單詞丧叽,肯定在一個txt文件中卫玖,分別統(tǒng)計單詞的出現(xiàn)頻率
step 6: 制作詞云
在這片文章的剩下內(nèi)容,我將針對這六個步驟進(jìn)行詳細(xì)講解:
tempDir = 'E:/研究生階段課程作業(yè)/python/好玩的數(shù)據(jù)分析/制作亞馬遜200G用戶評論詞云' #把評論數(shù)據(jù)分散到這個文件下下面的100個txt文件
pattern = re.compile(r'\w+') #編譯正則表達(dá)式踊淳,把短句轉(zhuǎn)化成list
def hashFile():
temp_path_list = []
for i in range(1,101):
temp_path_list.append(open(tempDir+'/'+str(i)+'.txt',mode='w'))
for each in (gzip.open(r'E:\研究生階段課程作業(yè)\python\zhihu_bigdata\complete.json.gz')):
sentence = eval(each) # turn string to dict
words = sentence['reviewText'] #提取 reviewText
words_list = pattern.findall(words) # example:words:"I love china" to words_list:["I","love","china"]
#print(words_list)
for word in words_list:
if not word.lower() in stopwords and len(word) >= 2: #忽略一些太簡單的單詞假瞬,例如“a”,"an",把你不想要的的單詞全部放在stopwords中迂尝。最好是set格式的stopwords脱茉。
word = word.lower() #全部為小寫單詞
print(hash(word)%100) #對單詞進(jìn)行hash,相同的單詞一定會hash到同一個文件中
temp_path_list[hash(word)%100].write(word+'\n') #寫入文件
for f in temp_path_list:
f.close()
hashFile()
以上的一段代碼垄开,首先是遍歷100G的數(shù)據(jù)琴许,提取每一行中的我們感興趣的部分。然后使用正則表達(dá)式溉躲,把字符串轉(zhuǎn)化成單詞列表榜田,過濾到我們不感興趣的單詞益兄。對剩下的單詞進(jìn)行hash,這樣我們可以把相同的單詞寫到同一個文件中箭券,因為我們的目標(biāo)是找出出現(xiàn)頻率前1000的單詞净捅,那么我們只要對這1000個文件,各自找出出現(xiàn)頻率在1000以內(nèi)的單詞邦鲫,在進(jìn)行排序灸叼,即可得出最終的結(jié)果神汹。
經(jīng)過上面的步驟庆捺,我們已經(jīng)把可能相同的單詞放在了一個文件中,共計100個文件
下面分別讀取每個文件到一個列表中
計算每個列表出現(xiàn)頻率最高的1000個單詞
最后在找出100個文件中出現(xiàn)頻率最高的1000個單詞
import os
from collections import Counter
results = Counter() # 初始化
for root, dirs, files in os.walk(r'E:\研究生階段課程作業(yè)\python\好玩的數(shù)據(jù)分析\制作亞馬遜200G用戶評論詞云'):
for file in files:
with open(os.path.join(root, file)) as f:
words_list = f.readlines()
words_list = list(map(lambda x: x.strip('\n'),words_list))
word_common_1000 = Counter(words_list).most_common(1000)
results.update(word_common_1000)
以上的一段代碼屁魏,把100個txt里面的單詞滔以,分別遍歷,找出每個出現(xiàn)頻率為1000的單詞氓拼,全部放在results中
import heapq
words_fren_list = list(results.keys())
words_fren_list_100 = heapq.nlargest(100,words_fren_list,key = lambda x:x[1])
哈哈大功告成你画,特別提醒一下,這里我是用了一個小的trick桃漾,找出出現(xiàn)頻率最高的100個單詞的時候坏匪,我并沒有對全部數(shù)據(jù)進(jìn)行排序,而是使用了heaapq中的nlarges函數(shù)撬统,可以提升不小的效率适滓。
最后根據(jù)這些詞出現(xiàn)的頻率,畫出詞云恋追。
from wordcloud import WordCloud
wordcloud = WordCloud(max_font_size=40, relative_scaling=.5).fit_words(words_fren_list_100)
import matplotlib.pyplot as plt
plt.imshow(wordcloud)
plt.axis("off")
plt.imshow()
最后的結(jié)果如下圖所示:
稍后我會把完整的代碼放在我的github上凭迹,如果你有疑惑或者想討論的內(nèi)容,請與我聯(lián)系:
Email: 1527927373@qq.com
QQ :1527927373