编辑2:更多异构数据。 (我已经离开了上面的方法,因为我发现每个系列处理相同数量的记录更常见)
回答问题的两个部分:
a) barh
返回它绘制的所有补丁的句柄容器。您可以使用补丁的坐标来帮助确定文本位置。
b) 关注these https://stackoverflow.com/a/16654415/1643946 two https://stackoverflow.com/a/16654564/1643946回答我之前提到的问题(参见Matplotlib 中的水平堆叠条形图 https://stackoverflow.com/q/16653815/1643946),您可以通过设置“左”输入水平堆叠条形图。
另外 c) 处理形状不太均匀的数据。
以下是处理形状不太均匀的数据的一种方法,即独立处理每个段。
import numpy as np
import matplotlib.pyplot as plt
# some labels for each row
people = ('A','B','C','D','E','F','G','H')
r = len(people)
# how many data points overall (average of 3 per person)
n = r * 3
# which person does each segment belong to?
rows = np.random.randint(0, r, (n,))
# how wide is the segment?
widths = np.random.randint(3,12, n,)
# what label to put on the segment (xrange in py2.7, range for py3)
labels = range(n)
colors ='rgbwmc'
patch_handles = []
fig = plt.figure(figsize=(10,8))
ax = fig.add_subplot(111)
left = np.zeros(r,)
row_counts = np.zeros(r,)
for (r, w, l) in zip(rows, widths, labels):
print r, w, l
patch_handles.append(ax.barh(r, w, align='center', left=left[r],
color=colors[int(row_counts[r]) % len(colors)]))
left[r] += w
row_counts[r] += 1
# we know there is only one patch but could enumerate if expanded
patch = patch_handles[-1][0]
bl = patch.get_xy()
x = 0.5*patch.get_width() + bl[0]
y = 0.5*patch.get_height() + bl[1]
ax.text(x, y, "%d%%" % (l), ha='center',va='center')
y_pos = np.arange(8)
ax.set_yticks(y_pos)
ax.set_yticklabels(people)
ax.set_xlabel('Distance')
plt.show()
Which produces a graph like this , with a different number of segments present in each series.
请注意,这并不是特别有效,因为每个段都使用单独的调用ax.barh
。可能有更有效的方法(例如,通过用零宽度段或 nan 值填充矩阵),但这可能是特定于问题的,并且是一个独特的问题。
编辑:更新以回答问题的两个部分。
import numpy as np
import matplotlib.pyplot as plt
people = ('A','B','C','D','E','F','G','H')
segments = 4
# generate some multi-dimensional data & arbitrary labels
data = 3 + 10* np.random.rand(segments, len(people))
percentages = (np.random.randint(5,20, (len(people), segments)))
y_pos = np.arange(len(people))
fig = plt.figure(figsize=(10,8))
ax = fig.add_subplot(111)
colors ='rgbwmc'
patch_handles = []
left = np.zeros(len(people)) # left alignment of data starts at zero
for i, d in enumerate(data):
patch_handles.append(ax.barh(y_pos, d,
color=colors[i%len(colors)], align='center',
left=left))
# accumulate the left-hand offsets
left += d
# go through all of the bar segments and annotate
for j in range(len(patch_handles)):
for i, patch in enumerate(patch_handles[j].get_children()):
bl = patch.get_xy()
x = 0.5*patch.get_width() + bl[0]
y = 0.5*patch.get_height() + bl[1]
ax.text(x,y, "%d%%" % (percentages[i,j]), ha='center')
ax.set_yticks(y_pos)
ax.set_yticklabels(people)
ax.set_xlabel('Distance')
plt.show()
您可以沿着这些方向获得结果(注意:我使用的百分比与条形宽度无关,因为示例中的关系似乎不清楚):
See Matplotlib 中的水平堆叠条形图 https://stackoverflow.com/q/16653815/1643946有关堆叠水平条形图的一些想法。