Chr*_*her 9 python plot matplotlib
我有一些数据列表,表明对一个(非常不满意)到五个(非常高兴)量表的回答.我想创建一个图表页面,将这些列表显示为倾斜堆叠的水平条形图.回复列表可以具有不同的大小(例如,当有人选择不回答特定问题时).以下是数据的最小示例:
likert1 = [1.0, 2.0, 1.0, 2.0, 1.0, 3.0, 3.0, 4.0, 4.0, 1.0, 1.0]
likert2 = [5.0, 4.0, 5.0, 4.0, 5.0, 3.0]
Run Code Online (Sandbox Code Playgroud)
我希望能够通过以下方式绘制:
plot_many_likerts(likert1, likert2)
Run Code Online (Sandbox Code Playgroud)
目前我已经编写了一个迭代列表的函数,并在matplotlib中的共享图上将每个函数绘制为自己的子图:
def plot_many_likerts(*lsts):
#get the figure and the list of axes for this plot
fig, axlst = plt.subplots(len(lsts), sharex=True)
for i in range(len(lsts)):
likert_horizontal_bar_list(lsts[i], axlst[i], xaxis=[1.0, 2.0, 3.0, 4.0, 5.0])
axlst[i].axis('off')
fig.show()
def likert_horizontal_bar_list(lst, ax, xaxis):
cnt = Counter(lst)
#del (cnt[None])
i = 0
colour_float = 0.00001
previous_right = 0
for key in sorted(xaxis):
ax.barh(bottom=0, width=cnt[key], height=0.4, left=previous_right, color=plt.cm.jet(colour_float),label=str(key))
i += 1
previous_right = previous_right + cnt[key]
colour_float = float(i) / float(len(xaxis))
Run Code Online (Sandbox Code Playgroud)
这种情况并不严重,并且创建具有相同代表尺寸的堆叠条形图(例如,宽度共享公共轴刻度).这是一个屏幕截图:
目前制作的是什么http://s7.postimg.org/vh0j816gn/figure_1.jpg
我想要的是让这两个图集中在数据集模式的中点(数据集将具有相同的范围).例如:
我想看看http://s29.postimg.org/z0qwv4ryr/figure_2.jpg
关于我如何做到这一点的建议?
我需要为一些类似的数据制作一个不同的条形图.我正在使用熊猫,但没有它,这种方法可能会相似.关键机制是在开始时添加一个不可见的缓冲区.
likert_colors = ['white', 'firebrick','lightcoral','gainsboro','cornflowerblue', 'darkblue']
dummy = pd.DataFrame([[1,2,3,4, 5], [5,6,7,8, 5], [10, 4, 2, 10, 5]],
columns=["SD", "D", "N", "A", "SA"],
index=["Key 1", "Key B", "Key III"])
middles = dummy[["SD", "D"]].sum(axis=1)+dummy["N"]*.5
longest = middles.max()
complete_longest = dummy.sum(axis=1).max()
dummy.insert(0, '', (middles - longest).abs())
dummy.plot.barh(stacked=True, color=likert_colors, edgecolor='none', legend=False)
z = plt.axvline(longest, linestyle='--', color='black', alpha=.5)
z.set_zorder(-1)
plt.xlim(0, complete_longest)
xvalues = range(0,complete_longest,10)
xlabels = [str(x-longest) for x in xvalues]
plt.xticks(xvalues, xlabels)
plt.show()
Run Code Online (Sandbox Code Playgroud)
这种方法有很多局限性.首先,条形图不再获得黑色轮廓,图例将有一个额外的空白元素.我只是隐藏了传说(我认为可能有一种方法可以隐藏单个元素).我不确定一种方便的方法,使条形图有一个轮廓,而不是在缓冲元素中添加轮廓.
首先,我们建立一些颜色和虚拟数据.然后我们计算左两列的宽度和最中间列的一半(我分别知道它是"SD","D"和"N").我找到了最长的列,并使用其宽度来计算其他列所需的差异.接下来,我将这个新的缓冲区列插入第一个列位置,并带有一个空白标题(感觉很糟糕,lemme告诉你).为了更好的衡量,我还根据[2]的建议在中间条的中间添加了一条垂直线(axvline).最后,我通过偏移其标签来调整x轴以获得适当的比例.
您可能需要更多左侧的水平空间 - 您可以通过添加"最长"来轻松实现.
[2] Heiberger,Richard M.和Naomi B. Robbins."设计用于李克特量表和其他应用的发散堆叠条形图." 统计软件期刊57.5(2014):1-32.
I too recently needed to make a divergent bar chart for some Likert data. I took a slightly different approach than @austin-cory-bart.
I modified an example from the gallery instead and created this:
import numpy as np
import matplotlib.pyplot as plt
category_names = ['Strongly disagree', 'Disagree',
'Neither agree nor disagree', 'Agree', 'Strongly agree']
results = {
'Question 1': [10, 15, 17, 32, 26],
'Question 2': [26, 22, 29, 10, 13],
'Question 3': [35, 37, 7, 2, 19],
'Question 4': [32, 11, 9, 15, 33],
'Question 5': [21, 29, 5, 5, 40],
'Question 6': [8, 19, 5, 30, 38]
}
def survey(results, category_names):
"""
Parameters
----------
results : dict
A mapping from question labels to a list of answers per category.
It is assumed all lists contain the same number of entries and that
it matches the length of *category_names*. The order is assumed
to be from 'Strongly disagree' to 'Strongly aisagree'
category_names : list of str
The category labels.
"""
labels = list(results.keys())
data = np.array(list(results.values()))
data_cum = data.cumsum(axis=1)
middle_index = data.shape[1]//2
offsets = data[:, range(middle_index)].sum(axis=1) + data[:, middle_index]/2
# Color Mapping
category_colors = plt.get_cmap('coolwarm_r')(
np.linspace(0.15, 0.85, data.shape[1]))
fig, ax = plt.subplots(figsize=(10, 5))
# Plot Bars
for i, (colname, color) in enumerate(zip(category_names, category_colors)):
widths = data[:, i]
starts = data_cum[:, i] - widths - offsets
rects = ax.barh(labels, widths, left=starts, height=0.5,
label=colname, color=color)
# Add Zero Reference Line
ax.axvline(0, linestyle='--', color='black', alpha=.25)
# X Axis
ax.set_xlim(-90, 90)
ax.set_xticks(np.arange(-90, 91, 10))
ax.xaxis.set_major_formatter(lambda x, pos: str(abs(int(x))))
# Y Axis
ax.invert_yaxis()
# Remove spines
ax.spines['right'].set_visible(False)
ax.spines['top'].set_visible(False)
ax.spines['left'].set_visible(False)
# Ledgend
ax.legend(ncol=len(category_names), bbox_to_anchor=(0, 1),
loc='lower left', fontsize='small')
# Set Background Color
fig.set_facecolor('#FFFFFF')
return fig, ax
fig, ax = survey(results, category_names)
plt.show()
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2845 次 |
| 最近记录: |