python寫程序統(tǒng)計(jì)詞頻的方法
在李笑來(lái)所著《時(shí)間當(dāng)作朋友》中有這么一段:
可問(wèn)題在于,當(dāng)年我在少年宮學(xué)習(xí)計(jì)算機(jī)程序語(yǔ)言的時(shí)候,怎么可能想象得到,在20多年后的某一天,我需要先用軟件調(diào)取語(yǔ)料庫(kù)中的數(shù)據(jù),然后用統(tǒng)計(jì)方法為每個(gè)單詞標(biāo)注詞頻,再寫一個(gè)批處理程序從相應(yīng)的字典里復(fù)制出多達(dá)20MB的內(nèi)容,重新整理……
在新書《自學(xué)是門手藝》中,他再次提及:
又過(guò)了好幾年,我去新東方教書。2003 年,在寫詞匯書的過(guò)程中,需要統(tǒng)計(jì)詞頻,C++ 倒是用不上,用之前學(xué)過(guò)它的經(jīng)驗(yàn),學(xué)了一點(diǎn) Python,寫程序統(tǒng)計(jì)詞頻 ——《TOEFL 核心詞匯 21 天突破》到今天還在銷售。一個(gè)當(dāng)年 10 塊錢學(xué)費(fèi)開始學(xué)的技能,就因?yàn)檫@本書,這些年給我 “變現(xiàn)” 了很多錢。
正在通過(guò)xue.cn 自學(xué) python 的我順手在 trello 中給自己添加一張卡片: 要不用 python 寫個(gè)統(tǒng)計(jì)詞頻的腳本玩玩? 這是前不久的事兒了。
今日周末,我翻出這張卡片,打算實(shí)踐看看。下文是我寫詞頻統(tǒng)計(jì)腳本時(shí)的一些思考與實(shí)踐成果。
2、如何把難題拆解為小CASE?
從需求來(lái)看,“統(tǒng)計(jì)詞頻的腳本”是一個(gè)泛泛的需求?!也⒉皇窍胍y(tǒng)計(jì)特定內(nèi)容的詞頻,我希望生成的腳本可以處理各式內(nèi)容。這對(duì)腳本的最終交付成果提出了高要求。
如果請(qǐng)你用 python 寫個(gè)統(tǒng)計(jì)詞頻的腳本,你會(huì)如何寫呢?當(dāng)我正襟危坐,正視這道題目時(shí),第一秒鐘感知到了為難與膽怯。有個(gè)小人兒在腦袋里說(shuō):“好難,我做不到吧?”
面對(duì)新事物、新挑戰(zhàn),人們善于用想象力把困難放的很大。而我已經(jīng)有了多次迎難而上的經(jīng)驗(yàn),于是我喝了一口苦咖啡,問(wèn)自己:
從哪兒下手呢?不如進(jìn)一步拆解來(lái)看看吧。
需求拆解如下:
“統(tǒng)計(jì)詞頻的腳本”,可以拆分為2個(gè)部分,a) 有哪些詞?b) 統(tǒng)計(jì)這些詞出現(xiàn)的次數(shù)。 b是簡(jiǎn)單的。 a分為2種情況:i) 給定詞庫(kù);ii) 自己從內(nèi)容中找詞。 i是簡(jiǎn)單的,ii則可能復(fù)雜。
此時(shí)你可能問(wèn),你是如何判斷簡(jiǎn)單還是復(fù)雜?簡(jiǎn)單吖,根據(jù)自己的編程能力與經(jīng)驗(yàn),預(yù)判自己能否寫出代碼。
需求經(jīng)過(guò)拆解后,當(dāng)前的重點(diǎn)聚焦于:
如何從內(nèi)容中抓取詞?
其中,內(nèi)容是一個(gè)寬泛的概念。在程序中,它可能是:string 常量,文件,網(wǎng)頁(yè),api 返回的數(shù)據(jù)如此等等。關(guān)鍵是什么呢?關(guān)鍵是腳本的一線代碼們處理的是 string,列表或字典。其余的文件、網(wǎng)頁(yè)、api 返回?cái)?shù)據(jù)等,無(wú)非是數(shù)據(jù)的載體更為復(fù)雜,我已經(jīng)掌握了把從它們那里獲取數(shù)據(jù),生成 string、列表或字典的能力。而這個(gè)能力你也能很簡(jiǎn)單獲得,即通過(guò)“python 如何讀取文件數(shù)據(jù)”之類句式,從搜索引擎中找到答案。
一篇文章可以直接定義或讀取為一個(gè) string 常量。而 for i in stringcontent
句式能夠幫我們遍歷 string 統(tǒng)計(jì)單個(gè)字的詞頻。然后雙字詞、三字詞、N字詞等等,都可以由單字詞拼接而成。
難點(diǎn)既然這么快想清楚,那么寫代碼實(shí)現(xiàn)吧!
3、從上帝視角調(diào)控成長(zhǎng)體驗(yàn)
第一個(gè)版本代碼如下圖所示,還是非常簡(jiǎn)便的。我在同個(gè)目錄下,另起一個(gè) poem.py
文件用來(lái)把內(nèi)容定義為常量,供該腳本調(diào)用。
首次測(cè)試的string 常量 poem 是一首中文小詩(shī),從常理來(lái)說(shuō),中文詞匯包括漢字1、2、3、4個(gè),超過(guò) 4 個(gè)的雖有但很少。順著上面的思路,我繼續(xù)把 3字詞、4字詞的代碼也寫出來(lái)了。運(yùn)算結(jié)果正常。
我想試試復(fù)雜的。比如讀取pdf文件。這涉及到一個(gè)我尚未掌握的新知識(shí)點(diǎn):python如何讀取pdf文件?獲取答案也很容易,搜索然后嘗試。
如果把“統(tǒng)計(jì)詞頻的python腳本”當(dāng)作主線任務(wù),那么“python如何讀取pdf文件”就是分支任務(wù)啦。在這個(gè)分支任務(wù)上我立即遇到困難:使用 anaconda powshell prompt 安裝第三方庫(kù)時(shí), pip install pdfminer
命令行執(zhí)行了小段就報(bào)錯(cuò)。
此時(shí)要么在支線任務(wù)中深究下去,要么回歸主線任務(wù)。我選擇回歸主線任務(wù),但順手在 trello 上給自己建卡“python如何讀取pdf文件”等以后專門來(lái)研究它。
現(xiàn)在,我繼續(xù)專注于詞頻腳本。
除了內(nèi)容載體的復(fù)雜,還可以有內(nèi)容量的冗長(zhǎng)。我拷貝了一篇幾千字的中文文章,定義為 string 常量,然后用剛才調(diào)試通過(guò)的腳本統(tǒng)計(jì)詞頻。
在處理數(shù)百字的小詩(shī)時(shí),腳本運(yùn)行迅速,結(jié)果幾乎立即被終端打印出來(lái)。而處理這篇長(zhǎng)文時(shí),終端打印完單字詞、雙字詞的統(tǒng)計(jì)結(jié)果后,就一直沒(méi)有輸出,好似“卡”在那里。于是我強(qiáng)制結(jié)束腳本,在代碼中添加了幾條打印來(lái)檢查程序是否正常運(yùn)行中。由此發(fā)現(xiàn)了一個(gè)“性能”上的問(wèn)題:電腦或編輯器,都沒(méi)有卡住,程序運(yùn)算持續(xù)在進(jìn)行中,只是沒(méi)有運(yùn)算完成。
這篇長(zhǎng)文,單字詞幾百條;按照我的上述代碼邏輯,雙字詞運(yùn)算 幾百*幾百 次,三字詞運(yùn)算 幾百*幾百 *幾百 次,四字詞運(yùn)算 幾百*幾百 *幾百 次。演算一下,具體是多少呢?
4字詞運(yùn)算次數(shù):467758877041 次
四千六百多億次!難怪遲遲沒(méi)有結(jié)果輸出!看來(lái)代碼本身需要被修改優(yōu)化,以降低計(jì)算量。第二個(gè)版本除了修改算法外,也調(diào)整了代碼結(jié)構(gòu),使之更易于調(diào)試和增刪。
在這個(gè)版本中,詞頻統(tǒng)計(jì)僅可用于中文,處理幾千字的文章,大概需要1分鐘左右。此時(shí),一個(gè)下午已經(jīng)過(guò)去了。再次久坐忘動(dòng)的我,決定暫停休息一下,扭扭脖子甩甩胳膊。而且,很重要的一件事是, 把實(shí)踐過(guò)程中的思考與第二個(gè)版本的腳本做一個(gè)階段交付 。
不得不提的是, 寫文章是一個(gè)提升階段交付成就感的小策略 。這也是此文的由來(lái)。當(dāng)然啦,我還要順手在 trello 上給自己添加2張新卡片,等有精力時(shí)繼續(xù)實(shí)踐:
python如何統(tǒng)計(jì)英文文章詞頻? python統(tǒng)計(jì)中文詞頻的腳本處理十幾萬(wàn)字的書籍時(shí),性能如何?
在群里談及我在寫的詞頻腳本時(shí),有位網(wǎng)友提出一個(gè)觀點(diǎn),“不是程序員,學(xué)編程沒(méi)用”。我想,他肯定是沒(méi)有讀過(guò)李笑來(lái)的書,或者干脆讀過(guò),只是讀成了另外一個(gè)版本吧!
如果你也在學(xué)習(xí) python 或想要提高自學(xué)能力,歡迎來(lái)xue.cn 聊天室找我 @liujuanjuan1984 ~
def write_rlt(content,dic1,dic2): rlt = {}#有該結(jié)果但并沒(méi)有用上 rlts = {} for i in dic1.keys(): for j in dic2.keys(): cix = i + j if cix in content: num = content.count(cix) if cix not in rlt.keys(): rlt[cix]=num if num > 1: rlts[cix]=num return rlts def cipin_1(content): rlt1 = {} rlt1s = {} for ci in content: #r"[^\u4e00-\u9fa5^a-z^A-Z^0-9]" atext =""" \ \\\\n ,.,。/一()()<>《》 """ if ci not in atext: num = content.count(ci) if ci not in rlt1.keys(): rlt1[ci]=num if num > 1: rlt1s[ci]=num return rlt1s def merge_dic(dic1,dic2): rlt = dic1.copy() rlt.update(dic2) return rlt def cipin_x(content,dic1,dic2): rltsx = write_rlt(content,dic1,dic2) rltsy = write_rlt(content,dic2,dic1) rlts = merge_dic(rltsx,rltsy) return rlts def sorted_dic(dic1,txt=None): rlt = sorted(dic1.items(),key=lambda x:x[1],reverse=True) print("\n--------------------\n") if txt==None: atxt = "結(jié)果共" else: atxt = txt + "字詞共" print(atxt,len(rlt),"條,具體為:\n",rlt) return rlt def main(): from txt import zixue_x as content #加載想要統(tǒng)計(jì)的內(nèi)容,string type import datetime print("---begin---",datetime.datetime.now()) rlt1s = cipin_1(content) rlt2s = cipin_x(content,rlt1s,rlt1s) rlt3s = cipin_x(content,rlt1s,rlt2s) rlt4s = cipin_x(content,rlt1s,rlt3s) rlt5s = cipin_x(content,rlt1s,rlt4s) rlt6s = cipin_x(content,rlt1s,rlt5s) rlt7s = cipin_x(content,rlt1s,rlt6s) sorted_dic(rlt1s,"單") sorted_dic(rlt2s,"雙") sorted_dic(rlt3s,"3") sorted_dic(rlt4s,"4") sorted_dic(rlt5s,"5") sorted_dic(rlt6s,"6") sorted_dic(rlt7s,"7") print("---end---",datetime.datetime.now()) if __name__ == "__main__": main()
這篇文章的 PRESS.one 簽名: press.one/file/v?s=33…
總結(jié)
以上所述是小編給大家介紹的python寫程序統(tǒng)計(jì)詞頻的方法,希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
如果你覺(jué)得本文對(duì)你有幫助,歡迎轉(zhuǎn)載,煩請(qǐng)注明出處,謝謝!
- 一文帶你掌握Python中文詞頻統(tǒng)計(jì)
- Python可視化單詞統(tǒng)計(jì)詞頻統(tǒng)計(jì)中文分詞的實(shí)現(xiàn)步驟
- python中文分詞+詞頻統(tǒng)計(jì)的實(shí)現(xiàn)步驟
- Python jieba 中文分詞與詞頻統(tǒng)計(jì)的操作
- python實(shí)現(xiàn)簡(jiǎn)單中文詞頻統(tǒng)計(jì)示例
- Python英文文章詞頻統(tǒng)計(jì)(14份劍橋真題詞頻統(tǒng)計(jì))
- python利用多種方式來(lái)統(tǒng)計(jì)詞頻(單詞個(gè)數(shù))
- Python統(tǒng)計(jì)中文詞頻的四種方法小結(jié)
相關(guān)文章
利用Python和OpenCV庫(kù)將URL轉(zhuǎn)換為OpenCV格式的方法
這篇文章主要介紹了利用Python和OpenCV庫(kù)將URL轉(zhuǎn)換為OpenCV格式的方法,同時(shí)用到了NumPy和urllib,需要的朋友可以參考下2015-03-03使用Python手工計(jì)算x的算數(shù)平方根,來(lái)自中國(guó)古人的數(shù)學(xué)智慧
本篇采用的計(jì)算方法既非二分法也非牛頓迭代法,而是把中國(guó)古代的手工計(jì)算平方根的方法轉(zhuǎn)成代碼來(lái)完成。代碼有點(diǎn)煩雜,算是拋磚引玉吧,期待高手們寫出更好的代碼來(lái)2021-09-09簡(jiǎn)單了解Django項(xiàng)目應(yīng)用創(chuàng)建過(guò)程
這篇文章主要介紹了簡(jiǎn)單了解Django項(xiàng)目應(yīng)用創(chuàng)建過(guò)程,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-07-07Python實(shí)戰(zhàn)之實(shí)現(xiàn)簡(jiǎn)易的學(xué)生選課系統(tǒng)
又到了小伙伴們最喜歡的python實(shí)戰(zhàn)環(huán)節(jié),文中對(duì)實(shí)現(xiàn)簡(jiǎn)易的學(xué)生選課系統(tǒng)作了非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)python的小伙伴們有很好的幫助,需要的朋友可以參考下2021-05-05Python通過(guò)for循環(huán)理解迭代器和生成器實(shí)例詳解
這篇文章主要介紹了Python通過(guò)for循環(huán)理解迭代器和生成器,結(jié)合實(shí)例形式詳細(xì)分析了迭代器和生成器的概念、原理、使用方法及相關(guān)操作技巧,需要的朋友可以參考下2019-02-02Python中sorted()函數(shù)之排序的利器詳解
sorted()函數(shù)是Python中的內(nèi)置函數(shù),用于對(duì)可迭代對(duì)象進(jìn)行排序,下面這篇文章主要給大家介紹了關(guān)于Python中sorted()函數(shù)之排序的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-08-08