Python在matplotlib中的两个列表之间创建单词图,以显示列表的通用性

时间:2018-04-10 18:43:37

标签: python matplotlib plot networkx

说我有两个单词列表,

list1 = ['Cat', 'Dog', 'Elephant', 'Giraffe' 'Monkey']
list2 = ['Cat', 'Dog', 'Eagle', 'Elephant', 'Monkey']

我想创建一个如下图:

Cat     ->  Cat
Dog     ->  Dog
Elephant \  Eagle
Giraffe   > Elephant
Monkey   -> Monkey

基本上,“梯形图”一词用箭头连接两个列表之间的每个常用词。如果list1中的给定单词在list2中没有对应单词(例如示例中的Eagle和Giraffe),则不需要箭头。

我不知道在matplotlib中这样做的方法。有没有人知道如何在matplotlib中执行此操作(可能与networkx一起使用?)?如果情节适用于任意数量的列表(例如,使用另一组箭头连接list2list3等),则奖励积分。

3 个答案:

答案 0 :(得分:3)

我认为将数据放入基于图表的表示形式对于所描述的问题来说是一个很好的方法,但也许你有一个用例,这个问题太重了。在前者中,@ xg.pltpy已经提出了建议。

这是使用强大的annotate功能在matplotlib中完成的一种方法。

import matplotlib.pyplot as plt

# define drawing of the words and links separately.
def plot_words(wordlist, col, ax):
    bbox_props = dict(boxstyle="round4,pad=0.3", fc="none", ec="b", lw=2)
    for i, word in enumerate(wordlist):
        ax.text(col, i, word, ha="center", va="center",
                size=12, bbox=bbox_props)

def plot_links(list1, list2, cols, ax):
    connectionstyle = "arc3,rad=0"
    for i, word in enumerate(list1):
        try: # do we need an edge?
            j = list2.index(word)
        except ValueError:
            continue # move on to the next word

        # define coordinates (relabelling here for clarity only)
        y1, y2 = i, j
        x1, x2 = cols
        # draw a line from word in 1st list to word in 2nd list
        ax.annotate("", xy=(x2, y2), xycoords='data',
                    xytext=(x1, y1), textcoords='data',
                    arrowprops=dict(
                        arrowstyle="->", color="k", lw=2,
                        shrinkA=25, shrinkB=25, patchA=None, patchB=None,
                        connectionstyle=connectionstyle,))



# define several lists
list1 = ['Cat', 'Dog', 'Elephant', 'Giraffe', 'Monkey']
list2 = ['Cat', 'Dog', 'Eagle', 'Elephant', 'Monkey']
list3 = ['Cat', 'Mouse', 'Horse', 'Elephant', 'Monkey']


# now plot them all -- words first then links between them
plt.figure(1); plt.clf()
fig, ax = plt.subplots(num=1)

plot_words(list1, col=1, ax=ax)
plot_words(list2, col=2, ax=ax)
plot_words(list3, col=0, ax=ax)
plot_links(list1, list2, ax=ax, cols=[1,2])
plot_links(list1, list3, ax=ax, cols=[1,0])

ax.set_xlim(-0.5, 2.5)
ax.set_ylim(-0.5, len(list1)+0.5)

cheap graph

箭头类型有很多选项,请参阅demo

在arrowprops中提供patchApatchB参数会更简洁,因为注释会自动剪切箭头长度以避免补丁(此处为单词)。我把它作为读者的练习;)

答案 1 :(得分:1)

结帐matplotlib.pyplot.text。您可以为图表上的某个点指定一个精确的let value: Option<_> = get_opt(); // 1: pattern matching if let Some(non_null_value) = value { // ... } // 2: functional methods let new_opt_value: Option<_> = value.map(|non_null_value| { "a new value" }).and_then(some_function_returning_opt); 坐标,它将会绘制&#39;那个词。

这是一个草率但有效的例子:

x,y

enter image description here

答案 2 :(得分:1)

以下是networkx的一个例子。

免责声明:for循环中的许多代码都可以简化并转换为单行(即位置和标签词典可以使用{{3轻松转换为python 3.5或更高版本中的单行代码}})。为清楚起见,我认为最好明确所有步骤。

第一步是在networkx中创建有向图。然后,对于list2中的每个元素,执行以下操作:

  • 节点图中的位置和标签存储在字典中。
  • 节点已添加到图表中。当重复列表中的元素时,节点名称不是list2中的动物,而是名称后跟'list2',以便具有不同的节点。这就是我们需要label_dict
  • 的原因

对于list1,执行相同的步骤,再增加一步:

  • 如果当前动物位于list2,请在图表中添加边缘

以下是示例代码,适用于列表的任何长度以及它们是否具有不同的长度。

import networkx as nx
list1 = ['Cat', 'Dog', 'Elephant', 'Giraffe', 'Monkey']
list2 = ['Cat', 'Dog', 'Eagle', 'Elephant', 'Monkey']
DG = nx.DiGraph()
pos_dict = {}; label_dict = {} # dictionary with the plot info
for i,animal in enumerate(list2):
    pos_dict['{}list2'.format(animal)] = (1,i)
    label_dict['{}list2'.format(animal)] = animal
    DG.add_node('{}list2'.format(animal))
for i,animal in enumerate(list1):
    pos_dict['{}list1'.format(animal)] = (0,i)
    label_dict['{}list1'.format(animal)] = animal
    DG.add_node('{}list1'.format(animal))
    if animal in list2:
        DG.add_edge('{}list1'.format(animal),'{}list2'.format(animal))

nx.draw_networkx(DG,
                 arrows=True,
                 with_labels=True,
                 node_color='w',
                 pos=pos_dict,
                 labels=label_dict,
                 node_size=2000)
plt.axis('off') # removes the axis to leave only the graph

使用networkx2.1的输出图像(在2.0中箭头看起来不同)是:

this answer