说我有两个单词列表,
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一起使用?)?如果情节适用于任意数量的列表(例如,使用另一组箭头连接list2
和list3
等),则奖励积分。
答案 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)
箭头类型有很多选项,请参阅demo。
在arrowprops中提供patchA
和patchB
参数会更简洁,因为注释会自动剪切箭头长度以避免补丁(此处为单词)。我把它作为读者的练习;)
答案 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
答案 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中箭头看起来不同)是: