我在一张图中有两个条形图子图。我想知道两个子图之间的条形总面积是如何比较的。我知道ax.bar()
返回一个Rectangle对象的集合,我试图用以下方式计算它们的区域:
from matplotlib import pyplot as plt
fig, (ax1, ax2) = plt.subplots(1,2)
def get_area(rects):
area = 0
for rect in rects:
area += rect.get_width() * rect.get_height()
return area
x = range(3)
y1 = [2, 3, 4]
y2 = [20, 30, 30]
r = ax1.bar(x, y1)
print "Total area of bars in first subplot = {:.1f}".format(get_area(r))
r = ax2.bar(x, y2)
print "Total area of bars in 2nd subplot = {:.1f}".format(get_area(r))
打印:
Total area of bars in first subplot = 7.2
Total area of bars in 2nd subplot = 64.0
从实际数字来看,这显然不是我想要捕捉的现实。
这似乎给了我“数据单元”中的区域,但我真正关心的是它们在屏幕上使用了多少空间。
答案 0 :(得分:1)
诀窍是使用ax.transData
从数据坐标转换为显示坐标。我发现变换上的this tutorial有助于解决这个问题。
from matplotlib import pyplot as plt
import numpy as np
def get_area(ax, rects):
area = 0
for rect in rects:
bbox = rect.get_bbox()
bbox_display = ax.transData.transform_bbox(bbox)
# For some reason, bars going right-to-left will have -ve width.
rect_area = abs(np.product(bbox_display.size))
area += rect_area
return area
fig, (ax1, ax2) = plt.subplots(1,2)
x = range(3)
y1 = [2, 3, 4]
y2 = [20, 30, 30]
r = ax1.bar(x, y1)
print "Real area of bars in first subplot = {:.1f}".format(get_area(ax1, r))
r = ax2.bar(x, y2)
print "Real area of bars in 2nd subplot = {:.1f}".format(get_area(ax2, r))
新输出:
Real area of bars in first subplot = 18417.7
Real area of bars in 2nd subplot = 21828.4
(小问题需要注意:bbox.size
有时会给出负宽度或高度。这个重复示例中没有问题,但是我在水平条形图上观察到了它从右边到-left。最好采取绝对值来保证安全。)