Python 代表范围的条形图
Python Barplot to represent Ranges
我想在 python 中制作一个分类图来表示几个变量的范围。我想也许我会使用条形图并为条形设置范围。这是我的条形图
import matplotlib.pyplot as plt
import numpy as np
data = {'a':.3, 'b': .3, 'c': .3, 'd': .1,'e':.1,'f':.1}
names = list(data.keys())
values = list(data.values())
plt.bar(names,values)
plt.show()
根据给定代码生成的条形图:
请告诉我如何将条形的值设置为 range(.3,.4)
之类的值。换句话说,我希望条形图从(.3 到 .4 代表一个范围)而不是(0 到 .3 当前的方式)。
我知道使用条形图来表示范围很奇怪,如果有人有其他方法可以做到这一点,请添加您的代码。我真的不在乎,只要我得到一个代表至少 6 个变量范围的图,我可以在其中轻松地手动更改范围的值。
一种方法是使用 LineCollection
并将线宽设置为类似于条形图。
要使用 LineCollection
,您需要提供一组 x 值来绘制 data
中提供的每个范围。为了创建与您的范围关联的 y 值,我使用了 np.arange
。由于 np.arange
只能计算整数,所以我将 data
中的每个值乘以 10,然后将结果除以 10 得到输入数据。
data = {'a':(.3,.4), 'b': (.3,.4), 'c': (.3,.4), 'd': (0,.1),'e':(0,.1),'f':(0,.1)}
names = list(data.keys())
values = list(data.values())
values = [np.arange(a[0]*10, (a[1]+0.1)*10,1)/10 for a in values]
xs = [np.ones(a.shape) for a in values]
xs = [i*a for i,a in zip(range(len(xs)), xs)]
verts = []
for x,y in zip(xs, values):
verts.append(list(zip(x.tolist(), y.tolist())))
lc = LineCollection(verts, linewidths=40)
fig,ax = plt.subplots()
ax.add_collection(lc)
ax.set_xlim(-0.5,len(values) )
plt.xticks(np.arange(len(values)), names)
更新答案
要解决 axvline
的问题,必须考虑宽度(像素)与范围的比率。我觉得这是一个hack。
因此,这里有一个使用axvspan
.
的解决方案
import numpy as np
from matplotlib import pyplot as plt
data = {'a':(0,.3), 'b': (0.2,.3), 'c': (.1,.3), 'd': (0.3,0.4),'e':(.1,.2),'f':(.1,.4)}
width = 0.5 # adjust to your liking
fig, ax = plt.subplots()
for i, values in enumerate(data.values()):
ymin, ymax = values
ax.axvspan(xmin=i-width/2, xmax=i+width/2, ymin=ymin,ymax=ymax)
# to illustrate that ranges are properly drawn
ax.grid(True)
#add ticks
ax.set_xticks(np.arange(0,len(data)))
ax.set_xticklabels(data.keys())
输出:
原回答
另一种选择是使用 axvline
:
from matplotlib import pyplot as plt
data = {'a':(0,.3), 'b': (0.2,.3), 'c': (.1,.3), 'd': (0.3,0.4),'e':(.1,.2),'f':(.1,.4)}
for key, values in data.items():
ymin, ymax = values
plt.axvline(x=key, ymin=ymin, ymax=ymax, lw=5)
输出:
如果需要,您可以通过调整 lw
来绘制条形图。
我想在 python 中制作一个分类图来表示几个变量的范围。我想也许我会使用条形图并为条形设置范围。这是我的条形图
import matplotlib.pyplot as plt
import numpy as np
data = {'a':.3, 'b': .3, 'c': .3, 'd': .1,'e':.1,'f':.1}
names = list(data.keys())
values = list(data.values())
plt.bar(names,values)
plt.show()
根据给定代码生成的条形图:
range(.3,.4)
之类的值。换句话说,我希望条形图从(.3 到 .4 代表一个范围)而不是(0 到 .3 当前的方式)。
我知道使用条形图来表示范围很奇怪,如果有人有其他方法可以做到这一点,请添加您的代码。我真的不在乎,只要我得到一个代表至少 6 个变量范围的图,我可以在其中轻松地手动更改范围的值。
一种方法是使用 LineCollection
并将线宽设置为类似于条形图。
要使用 LineCollection
,您需要提供一组 x 值来绘制 data
中提供的每个范围。为了创建与您的范围关联的 y 值,我使用了 np.arange
。由于 np.arange
只能计算整数,所以我将 data
中的每个值乘以 10,然后将结果除以 10 得到输入数据。
data = {'a':(.3,.4), 'b': (.3,.4), 'c': (.3,.4), 'd': (0,.1),'e':(0,.1),'f':(0,.1)}
names = list(data.keys())
values = list(data.values())
values = [np.arange(a[0]*10, (a[1]+0.1)*10,1)/10 for a in values]
xs = [np.ones(a.shape) for a in values]
xs = [i*a for i,a in zip(range(len(xs)), xs)]
verts = []
for x,y in zip(xs, values):
verts.append(list(zip(x.tolist(), y.tolist())))
lc = LineCollection(verts, linewidths=40)
fig,ax = plt.subplots()
ax.add_collection(lc)
ax.set_xlim(-0.5,len(values) )
plt.xticks(np.arange(len(values)), names)
更新答案
要解决 axvline
的问题,必须考虑宽度(像素)与范围的比率。我觉得这是一个hack。
因此,这里有一个使用axvspan
.
import numpy as np
from matplotlib import pyplot as plt
data = {'a':(0,.3), 'b': (0.2,.3), 'c': (.1,.3), 'd': (0.3,0.4),'e':(.1,.2),'f':(.1,.4)}
width = 0.5 # adjust to your liking
fig, ax = plt.subplots()
for i, values in enumerate(data.values()):
ymin, ymax = values
ax.axvspan(xmin=i-width/2, xmax=i+width/2, ymin=ymin,ymax=ymax)
# to illustrate that ranges are properly drawn
ax.grid(True)
#add ticks
ax.set_xticks(np.arange(0,len(data)))
ax.set_xticklabels(data.keys())
输出:
原回答
另一种选择是使用 axvline
:
from matplotlib import pyplot as plt
data = {'a':(0,.3), 'b': (0.2,.3), 'c': (.1,.3), 'd': (0.3,0.4),'e':(.1,.2),'f':(.1,.4)}
for key, values in data.items():
ymin, ymax = values
plt.axvline(x=key, ymin=ymin, ymax=ymax, lw=5)
输出:
如果需要,您可以通过调整 lw
来绘制条形图。