利用豆瓣短評數據生成詞雲

在以前的文章中,咱們得到了豆瓣爬取的短評內容,彙總到了一個文件中,可是,沒有被利用起來的數據是沒有意義的。html

前文提到,有一篇微信推文的關於詞雲製做的一個實踐記錄,準備照此試驗一下。python

思路分析

讀文件

利用with open() as...將文件讀進來。這裏須要注意文件內容的大小。git

分詞

因爲獲取的是大量的短評文字,而製做詞雲鬚要的是各類詞語,有了詞,才能談詞雲,因此目前第一步需求的就是講短評內容拆分紅一個個的中文詞彙。github

這裏就用到了我所聽過的一個庫jieba,能夠將中文語句拆解成一個個的詞彙。這裏是用的是lcut()方法,能將中文字符串拆解成一個列表,每項都是一個詞。正則表達式

清洗非中文

可是,咱們在分析中,須要的就是中文文字,因此須要將非中文字符完全清理,這裏使用了正則表達式。短小精悍的一個模式[\u4e00-\u9fa5]+便可匹配。express

使用正則表達式,個人習慣是如今網上的一些在線正則表達式工具上直接測試。其中oschina的不錯,還給提供了一些例子。canvas

在線正則表達式測試api

這裏是oschina的工具網站,作的很好。微信

工具分類索引markdown

處理停詞

因爲這些詞彙中,有不少詞是沒有實際分析價值的,因此咱們須要利用一個停詞文件來將沒必要要的詞處理掉。

參考文章中,是利用pandas庫彙總的方法read_csv()來處理停詞文件。,利用一個isin()方法實現了停詞。

聚合

詞分開了,基本也處理乾淨了。接下來應該考慮製做詞雲的問題。

咱們這裏想要重點突出在全部評論中的重要的核心觀點,爲了實現這樣的目的,咱們使用了分詞。

這彷佛是一種有些「斷章取義」的思路。藉助詞頻的分佈實現重點突出高詞頻內容的方式,來展示咱們的詞雲。

因此如今咱們須要作的事,就是處理詞彙的聚合問題,統計詞頻而已。

參考文種中利用了類DataFrame的分組方法group()和聚合方法agg()

關於這裏,參考文章中在agg()中使用了一個顯式的字典(可見文末參考文章),調用了numpy.size,可是彷佛是這種用法未來會被移除,查了一些文章,說是能夠這樣用,就是不能本身定製字典了。

FutureWarning: using a dict on a Series for aggregation is deprecated and will be removed in a future version

詞雲

這裏使用了第三方庫wordcloud。這個庫在安裝的時候,直接pip install wordcloud時,我出了問題,提示微軟開發工具的問題,折騰了半天,最後仍是直接在一個極爲豐富的第三方庫的集合站點上下載使用pip insatll了它的whl文件。

這下能夠正常使用了。

同時,這裏爲了可以顯示處理圖片,使用了matplotlib.pyplot&numpy來進行處理。

掩膜設置

wordcloud項目主頁README 瞭解,可使用二值圖像來設定掩膜(mask)。

出於提高數據的表現力,也出於學習的目的,這裏使用了直接編寫的rgb2gray()&gray2bw()函數來實現真彩圖像轉換爲二值圖像的過程。得到了最終的二值圖像掩膜。

這裏開始我並不知道須要怎樣的圖像,看了給的示例代碼,用的圖片的是二值圖像,才明白,白白浪費了好多時間。

並且,個人理解,由彩色轉爲二值圖像,是必要通過灰度圖像這個過程的。

關於matplotlib.pyplot的使用,網上都說,和matlab的語法很相似,之前瞭解過一點,因此看着例子中的imshow(),很天然的就想出了imread(),實現了圖片的讀取。

在查閱文檔的過程當中發現了一個有意思的地方。

文檔

Return value is a numpy.array. For grayscale images, the return array is MxN. For RGB images, the return value is MxNx3. For RGBA images the return value is MxNx4.
matplotlib can only read PNGs natively, but if PIL is installed, it will use it to load the image and return an array (if possible) which can be used with imshow(). Note, URL strings may not be compatible with PIL. Check the PIL documentation for more information.

我文中使用的是JPG圖像,可見是調用了PIL處理。

而這裏對於二值圖像的獲取,開始經歷了一個誤區。因爲在網上搜索的時候,搜到的大可能是利用PIL庫的Image模塊的open()&convert()方法的處理,附加參數1,能夠實現二值圖像的轉化,可是在這裏使用,後面在使用詞雲的時候,會提示缺乏屬性,可見這裏不適合這樣處理。

詞雲設定

詞雲支持自定義字體,背景顏色,掩膜設置等等,能夠直接在IDE中跳至源文件中查看。都有相關的介紹。

文末代碼是一些參數的摘錄。

詞頻選擇

這裏使用了剛纔聚合排序好的數據,選擇了前1000個詞進行展現,並組合成字典,傳入了詞雲的實例對象的方法fit_words()生成了詞雲。

詞雲展現

這裏使用了matplotlib.pyplot的的幾個函數,實現了圖像的保存,顯示,以及座標軸的隱藏。

這裏卻是有個小異或,有點分不清楚imshow()show()了。二者從文檔我也沒看出個因此然來。不過他們有個最明顯的區別就是後者依賴圖形窗口,可是前者彷佛不須要。

要是有明白的,還請你們留言或者發郵件給我。

完整代碼

# -*- coding: utf-8 -*-
"""
Created on Thu Aug 17 16:31:35 2017

@note: 爲了便於閱讀,將模塊的引用就近安置了
@author: lart
"""

# 讀取事先爬取好的文件,因爲文件較小,直接一次性讀入。若文件較大,則最好分體積讀入。
with open('祕密森林的短評.txt', 'r', encoding='utf-8') as file:
    comments = file.readlines()
    comment = ''.join(comments)


# 摘取中文字符,沒有在下載時處理,正好保留原始數據。
import re

pattern = re.compile(r'[\u4e00-\u9fa5]+')
data = pattern.findall(comment)
filted_comment = ''.join(data)

# 分詞
import jieba

word = jieba.lcut(filted_comment)


# 整理
import pandas as pd

words_df = pd.DataFrame({'words': word})

#停詞相關設置。參數 quoting=3 全不引用
stopwords = pd.read_csv(
        "stopwords.txt",
        index_col=False,
        quoting=3,
        sep="\t",
        names=['stopword'],
        encoding='utf-8'
        )
words_df = words_df[~words_df.words.isin(stopwords.stopword)]

# 聚合
words_stat = words_df.groupby('words')['words'].agg({'size'})
words_stat = words_stat.reset_index().sort_values("size", ascending=False)


# 詞雲設置
from wordcloud import WordCloud
import matplotlib.pyplot as plt
import numpy as np

def rgb2gray(rgb):
    return np.dot(rgb[...,:3], [0.299, 0.587, 0.114])

def gray2bw(gray):
    for raw in range(len(gray)):
        for col in range(len(gray[raw])):
            gray[raw][col] = (0 if gray[raw][col]>50 else 255)
    return gray

img = plt.imread('4.jpg')
mask = rgb2gray(img)
bw = gray2bw(mask)

wordcloud = WordCloud(
                font_path="YaHei Consolas Hybrid.ttf",
                background_color="white",
                mask=bw,
                max_font_size=80
                )
# word_frequence 爲字典類型,能夠直接傳入wordcloud.fit_words()
word_frequence = {
        x[0]:x[1] for x in words_stat.head(1000).values
        }
wordcloud = wordcloud.fit_words(word_frequence)

# 存儲顯示
plt.imsave('img.jpg', wordcloud)

plt.subplot(131)
plt.imshow(img)
plt.axis("off")
plt.subplot(132)
plt.imshow(bw)
plt.axis("off")
plt.subplot(133)
plt.imshow(wordcloud, interpolation='bilinear')
plt.axis("off")

結果文件

使用的掩膜原圖片:

祕密森林劇照

祕密森林劇照

輸出圖片

輸出圖片

IDE輸出結果

這裏寫圖片描述

停詞文件

stopwords.txt


參考文章

Parameters
----------
font_path : string
    Font path to the font that will be used (OTF or TTF).
    Defaults to DroidSansMono path on a Linux machine. If you are on
    another OS or don't have this font, you need to adjust this path.

width : int (default=400)
    Width of the canvas.

height : int (default=200)
    Height of the canvas.

prefer_horizontal : float (default=0.90)
    The ratio of times to try horizontal fitting as opposed to vertical.
    If prefer_horizontal < 1, the algorithm will try rotating the word
    if it doesn't fit. (There is currently no built-in way to get only
    vertical words.)

mask : nd-array or None (default=None)
    If not None, gives a binary mask on where to draw words. If mask is not
    None, width and height will be ignored and the shape of mask will be
    used instead. All white (#FF or #FFFFFF) entries will be considerd
    "masked out" while other entries will be free to draw on. [This
    changed in the most recent version!]

scale : float (default=1)
    Scaling between computation and drawing. For large word-cloud images,
    using scale instead of larger canvas size is significantly faster, but
    might lead to a coarser fit for the words.

min_font_size : int (default=4)
    Smallest font size to use. Will stop when there is no more room in this
    size.

font_step : int (default=1)
    Step size for the font. font_step > 1 might speed up computation but
    give a worse fit.

max_words : number (default=200)
    The maximum number of words.

stopwords : set of strings or None
    The words that will be eliminated. If None, the build-in STOPWORDS
    list will be used.

background_color : color value (default="black")
    Background color for the word cloud image.

max_font_size : int or None (default=None)
    Maximum font size for the largest word. If None, height of the image is
    used.

mode : string (default="RGB")
    Transparent background will be generated when mode is "RGBA" and
    background_color is None.

relative_scaling : float (default=.5)
    Importance of relative word frequencies for font-size.  With
    relative_scaling=0, only word-ranks are considered.  With
    relative_scaling=1, a word that is twice as frequent will have twice
    the size.  If you want to consider the word frequencies and not only
    their rank, relative_scaling around .5 often looks good.

    .. versionchanged: 2.0
        Default is now 0.5.

color_func : callable, default=None
    Callable with parameters word, font_size, position, orientation,
    font_path, random_state that returns a PIL color for each word.
    Overwrites "colormap".
    See colormap for specifying a matplotlib colormap instead.

regexp : string or None (optional)
    Regular expression to split the input text into tokens in process_text.
    If None is specified, ``r"\w[\w']+"`` is used.

collocations : bool, default=True
    Whether to include collocations (bigrams) of two words.

    .. versionadded: 2.0

colormap : string or matplotlib colormap, default="viridis"
    Matplotlib colormap to randomly draw colors from for each word.
    Ignored if "color_func" is specified.

    .. versionadded: 2.0

normalize_plurals : bool, default=True
    Whether to remove trailing 's' from words. If True and a word
    appears with and without a trailing 's', the one with trailing 's'
    is removed and its counts are added to the version without
    trailing 's' -- unless the word ends with 'ss'.
相關文章
相關標籤/搜索