Плотно возвращая пустой объект фигуры - PullRequest
0 голосов
/ 09 ноября 2018

У меня есть следующий код, который должен отобразить облако слов данного текста в matplotlib и преобразовать его в плотно:

from wordcloud import WordCloud, STOPWORDS
import matplotlib.pyplot as plt
import plotly.graph_objs as go
from plotly.offline import download_plotlyjs, init_notebook_mode, plot, iplot
import plotly.tools as tls

# Thanks : https://www.kaggle.com/aashita/word-clouds-of-various-shapes ##
def plot_wordcloud(text, mask=None, max_words=200, max_font_size=100, figure_size=(24.0,16.0), 
                   title = None, title_size=40, image_color=False):
    stopwords = set(STOPWORDS)
    wordcloud = WordCloud(background_color='black',
                    stopwords = stopwords,
                    max_words = max_words,
                    max_font_size = max_font_size, 
                    random_state = 42,
                    width=800, 
                    height=400,
                    mask = mask)
    wordcloud.generate(str(text))

    fig = plt.figure()
    plt.imshow(wordcloud)
    return tls.mpl_to_plotly(fig)

word_list = "Wikipedia was launched on January 15, 2001, by Jimmy Wales and Larry Sanger.[10] Sanger coined its name,[11][12] as a portmanteau of wiki[notes 3] and 'encyclopedia'. Initially an English-language encyclopedia, versions in other languages were quickly developed. With 5,748,461 articles,[notes 4] the English Wikipedia is the largest of the more than 290 Wikipedia encyclopedias. Overall, Wikipedia comprises more than 40 million articles in 301 different languages[14] and by February 2014 it had reached 18 billion page views and nearly 500 million unique visitors per month.[15] In 2005, Nature published a peer review comparing 42 science articles from Encyclopædia Britannica and Wikipedia and found that Wikipedia's level of accuracy approached that of Britannica.[16] Time magazine stated that the open-door policy of allowing anyone to edit had made Wikipedia the biggest and possibly the best encyclopedia in the world and it was testament to the vision of Jimmy Wales.[17] Wikipedia has been criticized for exhibiting systemic bias, for presenting a mixture of 'truths, half truths, and some falsehoods',[18] and for being subject to manipulation and spin in controversial topics.[19] In 2017, Facebook announced that it would help readers detect fake news by suitable links to Wikipedia articles. YouTube announced a similar plan in 2018."

plot_wordcloud(word_list, title="Word Cloud")

Это просто возвращает пустую цифру с пустым значением в части data:

Figure({
    'data': [],
    'layout': {'autosize': False,
               'height': 288,
               'hovermode': 'closest',
               'margin': {'b': 61, 'l': 54, 'pad': 0, 'r': 43, 't': 59},
               'showlegend': False,
               'width': 432,
               'xaxis': {'anchor': 'y',
                         'domain': [0.0, 1.0],
                         'mirror': 'ticks',
                         'nticks': 10,
                         'range': [-0.5, 799.5],
                         'showgrid': False,
                         'showline': True,
                         'side': 'bottom',
                         'tickfont': {'size': 10.0},
                         'ticks': 'inside',
                         'type': 'linear',
                         'zeroline': False},
               'yaxis': {'anchor': 'x',
                         'domain': [0.0, 1.0],
                         'mirror': 'ticks',
                         'nticks': 10,
                         'range': [399.5, -0.5],
                         'showgrid': False,
                         'showline': True,
                         'side': 'left',
                         'tickfont': {'size': 10.0},
                         'ticks': 'inside',
                         'type': 'linear',
                         'zeroline': False}}
})

Почему это? И как мне это исправить?

Если я хочу построить график matplotlib, он работает нормально - return fig возвращает статическую фигуру wordcloud.

Я пытался напрямую построить слово wordcloud, но с go.Scatter вам нужно явно указать значения x и y - он не может получить их из wordcloud неявно, как plt.imshow. Итак, я получаю ошибку «объект не повторяем»:

def plot_wordcloud(text, mask=None, max_words=200, max_font_size=100, figure_size=(24.0,16.0), 
                   title = None, title_size=40, image_color=False):
    stopwords = set(STOPWORDS)
    wordcloud = WordCloud(background_color='black',
                    stopwords = stopwords,
                    max_words = max_words,
                    max_font_size = max_font_size, 
                    random_state = 42,
                    width=800, 
                    height=400,
                    mask = mask)
    wordcloud.generate(str(text))


    data = go.Scatter(dict(wordcloud.generate(str(text))),
                 mode='text',
                 text=words,
                 marker={'opacity': 0.3},
                 textfont={'size': weights,
                           'color': colors})
    layout = go.Layout({'xaxis': {'showgrid': False, 'showticklabels': False, 'zeroline': False},
                        'yaxis': {'showgrid': False, 'showticklabels': False, 'zeroline': False}})
    fig = go.Figure(data=[data], layout=layout)
    return fig


word_list = "Wikipedia was launched on January 15, 2001, by Jimmy Wales and Larry Sanger.[10] Sanger coined its name,[11][12] as a portmanteau of wiki[notes 3] and 'encyclopedia'. Initially an English-language encyclopedia, versions in other languages were quickly developed. With 5,748,461 articles,[notes 4] the English Wikipedia is the largest of the more than 290 Wikipedia encyclopedias. Overall, Wikipedia comprises more than 40 million articles in 301 different languages[14] and by February 2014 it had reached 18 billion page views and nearly 500 million unique visitors per month.[15] In 2005, Nature published a peer review comparing 42 science articles from Encyclopædia Britannica and Wikipedia and found that Wikipedia's level of accuracy approached that of Britannica.[16] Time magazine stated that the open-door policy of allowing anyone to edit had made Wikipedia the biggest and possibly the best encyclopedia in the world and it was testament to the vision of Jimmy Wales.[17] Wikipedia has been criticized for exhibiting systemic bias, for presenting a mixture of 'truths, half truths, and some falsehoods',[18] and for being subject to manipulation and spin in controversial topics.[19] In 2017, Facebook announced that it would help readers detect fake news by suitable links to Wikipedia articles. YouTube announced a similar plan in 2018."

plot_wordcloud(word_list, title="Word Cloud")

---------------------------------------------------------------------------

TypeError                                 Traceback (most recent call last)
<ipython-input-50-0567281b72b3> in <module>()

---> 48 plot_wordcloud(word_list, title="Word Cloud")

<ipython-input-50-0567281b72b3> in plot_wordcloud(text, mask, max_words, max_font_size, figure_size, title, title_size, image_color)
     18 
     19 
---> 20     data = go.Scatter(dict(wordcloud.generate(str(text))),
     21                  mode='text',
     22                  text=words,

TypeError: 'WordCloud' object is not iterable

Если я return wordcloud, он отображает это: <wordcloud.wordcloud.WordCloud at 0x1c8faeda748>. Если кто-нибудь знает, как распаковать объект wordcloud, чтобы я мог ввести параметры x и y из него в go.Figure, это также было бы здорово (на самом деле лучше).


Просто чтобы показать, что распаковка объекта wordcloud сработает, я могу встроить графическое облако слов с помощью заговора, поместив случайные числа для значений x и y в go.Scatter следующим образом:

import random
import plotly.graph_objs as go

def plot_wordcloud(text, mask=None, max_words=200, max_font_size=100, figure_size=(24.0,16.0), 
                   title = None, title_size=40, image_color=False):
    stopwords = set(STOPWORDS)
    wordcloud = WordCloud(background_color='black',
                    stopwords = stopwords,
                    max_words = max_words,
                    max_font_size = max_font_size, 
                    random_state = 42,
                    width=800, 
                    height=400,
                    mask = mask)
    wordcloud.generate(str(text))


    data = go.Scatter(x=[random.random() for i in range(3000)],
                 y=[random.random() for i in range(3000)],
                 mode='text',
                 text=str(word_list).split(),
                 marker={'opacity': 0.3},
                 textfont={'size': weights,
                           'color': colors})
    layout = go.Layout({'xaxis': {'showgrid': False, 'showticklabels': False, 'zeroline': False},
                        'yaxis': {'showgrid': False, 'showticklabels': False, 'zeroline': False}})
    fig = go.Figure(data=[data], layout=layout)
    return fig

enter image description here

Это просто не правильное слово-облако (очевидно, с правильно определенными позициями и размерами слов), которое должно выглядеть следующим образом (статическое слово-облако, нанесенное с помощью matplotlib.pyplot):

enter image description here

1 Ответ

0 голосов
/ 12 ноября 2018

Поскольку wordcloud создает изображение, а функция преобразования плоттеров в настоящее время не может обрабатывать изображения, вам необходимо каким-то образом восстановить облако слов из позиций, размеров и ориентаций объекта wordcloud.wordcloud.WordCloud.

Эта информация хранится в атрибуте .layout_

.
wc = Wordcloud(...)
wc.generate(text)
print(wc.layout_)

печатает список кортежей вида

[(word, freq), fontsize, position, orientation, color]

например. в этом случае

[(('Wikipedia', 1.0), 100, (8, 7), None, 'rgb(56, 89, 140)'), 
 (('articles', 0.4444444444444444), 72, (269, 310), None, 'rgb(58, 186, 118)'), ...]

Так что в принципе это позволяет регенерировать облако слов как текст. Однако следует позаботиться о мелких деталях. То есть шрифт и размер шрифта должны быть одинаковыми.

Вот пример чистого matplotlib, который воспроизводит облако слов с matplotlib.text.Text объектами.

import numpy as np
from wordcloud import WordCloud, STOPWORDS 
from wordcloud.wordcloud import FONT_PATH
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties

word_list = "Wikipedia was launched on January 15, 2001, by Jimmy Wales and Larry Sanger.[10] Sanger coined its name,[11][12] as a portmanteau of wiki[notes 3] and 'encyclopedia'. Initially an English-language encyclopedia, versions in other languages were quickly developed. With 5,748,461 articles,[notes 4] the English Wikipedia is the largest of the more than 290 Wikipedia encyclopedias. Overall, Wikipedia comprises more than 40 million articles in 301 different languages[14] and by February 2014 it had reached 18 billion page views and nearly 500 million unique visitors per month.[15] In 2005, Nature published a peer review comparing 42 science articles from Encyclopædia Britannica and Wikipedia and found that Wikipedia's level of accuracy approached that of Britannica.[16] Time magazine stated that the open-door policy of allowing anyone to edit had made Wikipedia the biggest and possibly the best encyclopedia in the world and it was testament to the vision of Jimmy Wales.[17] Wikipedia has been criticized for exhibiting systemic bias, for presenting a mixture of 'truths, half truths, and some falsehoods',[18] and for being subject to manipulation and spin in controversial topics.[19] In 2017, Facebook announced that it would help readers detect fake news by suitable links to Wikipedia articles. YouTube announced a similar plan in 2018."

def get_wordcloud(width, height):
    wc = WordCloud(background_color='black',
                    stopwords = set(STOPWORDS),
                    max_words = 200,
                    max_font_size = 100, 
                    random_state = 42,
                    width=int(width), 
                    height=int(height),
                    mask = None)
    wc.generate(word_list)
    return wc


fig, (ax, ax2) = plt.subplots(nrows=2, sharex=True, sharey=True)

fp=FontProperties(fname=FONT_PATH)
bbox = ax.get_position().transformed(fig.transFigure)
wc = get_wordcloud(bbox.width, bbox.height)

ax.imshow(wc)

ax2.set_facecolor("black")
for (word, freq), fontsize, position, orientation, color in wc.layout_:
    color = np.array(color[4:-1].split(", ")).astype(float)/255.
    x,y = position
    rot = {None : 0, 2: 90}[orientation]
    fp.set_size(fontsize*72./fig.dpi)
    ax2.text(y,x, word, va="top", ha="left", color=color, rotation=rot, 
             fontproperties=fp)

print(wc.layout_)
plt.show()

enter image description here

Верхний график - это изображение облака слов, показанное с помощью imshow, нижний график - восстановленное облако слов.

Теперь вы можете сделать то же самое в графике, а не в matplotlib, но я недостаточно опытен с графиком, чтобы напрямую дать решение здесь.

...