2017-03-15 13 views
1

私は頭の中に何かの精神的なマップを持っています。私はそれをRでプログラムする方法を見つけようとしていますし、ちょっと迷っています(おそらくRは最適ではない)これについてあなたの意見を求めています。Auto-Venn Diagramのテキストレンダリング

は、ここでの考え方です:

(1)私は、民主党と共和党でトップ30で最も使用されている単語に2ビットの情報それぞれ[単語、周波数]を含んで毎日のための2つのリストを持っています。

(2)Iは (A)は周波数 (B)にそのフォントサイズの相対有する単語のテキストを自動的両方で使用される単語を置くレンダリングすること描かdigram等ベンまたはオイラーしたいと思います当事者はダイアグラムの中央部に入り、ユニークな民主党や共和国の言葉を自分の部分に入れます。

これまではVennDiagramとVennerableとVenneulerのパッケージを使っていましたが、何も正しくなく、私。クローズアップ(​​)を取得するいくつかのオンラインツールがありますが、私は毎日自動更新できるものが欲しいと思います。

アイデア?

+0

一つの可能​​性ではなく、ワードクラウドを使用することです。 – lmo

+1

xyプロットを使用できますか? y = x行は、その行の上/下の交差点を各パーティーのユニークな単語で保持します。 – Fernando

答えて

0

私は飽きてしまった:

enter image description here

import numpy as np 
import matplotlib.pyplot as plt 

FIG_SIZE = (10,6) 

class word_list_venn_diagram(object): 

    def __init__(self, words, fontsizes, polarities, scale=1.): 
     """ 
     Arguments: 
     ---------- 
      words: [str 1, ... str N] 
       list of strings 
      fontsizes: [float 1, ... float N] 
       corresponding list of (relative) fontsizes 
      polarity: [-1, 0, 1, ..., 0, 1] 
       corresponding list of area designations; 
       polarity of 0 corresponds to intersection; 
       polarities -1 and 1 correspond to the disjoint sets 
      scale: float 
       scales the size of the circles with respect to the text 
       (w.r.t. the maximum joint height of the bounding boxes of the 3 word lists) 

     Returns: 
     -------- 
      None 

     """ 

     self.words = np.array(words) 
     self.fontsizes = np.array(fontsizes) 

     # get bounding boxes of text 
     self.bboxes = [self._get_bbox(word, size) for word, size in zip(self.words, self.fontsizes)] 

     # determine minimum radius of circles 
     diameter = 0. 
     unique_polarities = np.unique(polarities) 
     for polarity in unique_polarities: 
      idx, = np.where(polarities == polarity) 
      heights = [self.bboxes[ii].height for ii in idx] 
      total = np.sum(heights) 
      if total > diameter: 
       diameter = total 
     radius = diameter/2. 

     # rescale 
     radius *= scale 
     self.radius = radius 

     # arrange bboxes vertically 
     for polarity in unique_polarities: 
      idx, = np.where(polarities == polarity) 
      order = self._argsort(self.fontsizes[idx]) 
      heights = [self.bboxes[ii].height for ii in idx] 
      total = np.sum(heights) 

      current_height = 0. 
      for ii in idx[order]: 
       self.bboxes[ii].y = current_height - total/2. 
       current_height += self.bboxes[ii].height 

     # arrange bboxes horizontally 
     # NB: slightly cheeky use of polarity argument 
     for ii, _ in enumerate(self.bboxes): 
      self.bboxes[ii].x = polarities[ii] * self._get_shift(self.bboxes[ii].y, self.radius) 

     # draw 
     self.fig, self.ax = self.draw() 

     return 

    def draw(self): 
     """ 
     Draws the Venn diagram. 
     """ 

     fig, ax = plt.subplots(1,1,figsize=FIG_SIZE) 

     # draw circles 
     circle_left = plt.Circle((-0.5*self.radius, 0), self.radius, color='b', fill=False, axes=ax, linewidth=5) 
     circle_right = plt.Circle((+0.5*self.radius, 0), self.radius, color='r', fill=False, axes=ax, linewidth=5) 
     ax.add_artist(circle_left) 
     ax.add_artist(circle_right) 

     # draw words 
     for ii, (word, bb, fs) in enumerate(zip(self.words, self.bboxes, self.fontsizes)): 
      ax.text(bb.x, bb.y, word, 
        horizontalalignment='center', 
        verticalalignment='center', 
        fontsize=fs, 
        bbox=dict(pad=0., facecolor='none', edgecolor='none') 
      ) 

     # update data limits as circles are not registered automatically 
     corners = (-1.5*self.radius, -self.radius), (1.5*self.radius, self.radius) 
     ax.update_datalim(corners) 
     ax.autoscale_view() 

     # make figure pretty-ish 
     ax.set_xticks([]) 
     ax.set_yticks([]) 
     ax.set_aspect('equal') 
     ax.get_figure().set_facecolor('w') 
     ax.set_frame_on(False) 
     ax.get_figure().canvas.draw() 

     return fig, ax 

    def _get_bbox(self, word, fontsize): 
     """ 
     Get the bounding box for each word. 
     Unfortunately, the bbox is dependent on the renderer, 
     so a figure has to be created. 
     """ 
     fig = plt.figure(figsize=FIG_SIZE) 
     renderer = fig.canvas.get_renderer() 
     text = plt.text(0.5, 0.5, word, 
         fontsize=fontsize, 
         bbox=dict(pad=0., facecolor='none', edgecolor='red')) 
     bbox = text.get_window_extent(renderer=renderer) 
     plt.close(fig) 
     return bbox 

    def _argsort(self, arr): 
     """ 
     Returns indices to create a sorted array. 
     Entries are sorted in such a way that the largest element is in the middle, 
     and the size of the elements falls off towards the ends. 
     """ 
     order = np.argsort(arr) 
     order = np.r_[order[::2], order[1::2][::-1]] 
     return order 

    def _get_shift(self, y, r): 
     """ 
     Get point along midline of a waxing moon formed by two overlapping 
     circles of radius r as a function of y. 
     """ 
     x1 = np.sqrt(r**2 - y**2) + r/2. # right circle 
     x2 = np.sqrt(r**2 - y**2) - r/2. # left circle 
     x = x2 + (x1 - x2)/2. # midpoint 
     return x 

def test(): 

    test_string = "Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet." 

    # get a word list 
    words = test_string.split(' ') 

    # remove non alphanumeric characters 
    words = [''.join(ch for ch in word if ch.isalnum()) for word in words] 

    # count occurrences; remove duplicates 
    from collections import Counter 
    counter = Counter() 
    for word in words: 
     counter[word] += 1 
    words, counts = counter.keys(), np.array(counter.values()) 

    # convert counts to reasonable fontsizes 
    max_fontsize = 25 
    max_count = np.float(np.max(counts)) 
    fontsizes = counts/max_count * max_fontsize 

    # assign random polarities 
    polarities = np.random.choice([-1, 0, 1], len(words)) 

    venn = word_list_venn_diagram(words, fontsizes, polarities, scale=1.5) 

    return 
関連する問題