我正在寻找一种在matplotlib中为每个值绘制多个条形图的方法。对于数值数据,可以通过向X数据添加偏移量来实现,例如here所述:
import numpy as np
import matplotlib.pyplot as plt
X = np.array([1,3,5])
Y = [1,2,3]
Z = [2,3,4]
plt.bar(X - 0.4, Y) # offset of -0.4
plt.bar(X + 0.4, Z) # offset of 0.4
plt.show()
plt.bar()
(和ax.bar()
)也会自动处理分类数据:
X = ['A','B','C']
Y = [1,2,3]
plt.bar(X, Y)
plt.show()
这里,显然不可能添加偏移量,因为类别不与轴上的值直接关联。我可以手动为类别分配数值,并使用plt.xticks()
:,
X = ['A','B','C']
Y = [1,2,3]
Z = [2,3,4]
_X = np.arange(len(X))
plt.bar(_X - 0.2, Y, 0.4)
plt.bar(_X + 0.2, Z, 0.4)
plt.xticks(_X, X) # set labels manually
plt.show()
但是,我想知道是否有一种更优雅的方式可以使用bar()
的自动类别处理,特别是如果以前不知道每个类别的类别和条形数量(这个导致一些摆弄条宽以避免重叠。)
答案 0 :(得分:14)
matplotlib中没有子类别的自动支持。
你可以采用数字方式放置条形图,就像你在问题中提出自己一样。您当然可以让代码管理未知数量的子类别。
import numpy as np
import matplotlib.pyplot as plt
X = ['A','B','C']
Y = [1,2,3]
Z = [2,3,4]
def subcategorybar(X, vals, width=0.8):
n = len(vals)
_X = np.arange(len(X))
for i in range(n):
plt.bar(_X - width/2. + i/float(n)*width, vals[i],
width=width/float(n), align="edge")
plt.xticks(_X, X)
subcategorybar(X, [Y,Z,Y])
plt.show()
您也可以使用pandas plotting wrapper,它负责计算子类别的数量。它将在数据帧的每列中绘制一个组。
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
X = ['A','B','C']
Y = [1,2,3]
Z = [2,3,4]
df = pd.DataFrame(np.c_[Y,Z,Y], index=X)
df.plot.bar()
plt.show()