如何为不同长度的绘图设置相同的边距?

2024-06-01 01:27:54 发布

您现在位置:Python中文网/ 问答频道 /正文

我需要为每个学校的年级和学期绘制一个条形图,我需要为大约60所学校做这个。但由于有些学校的分数比其他学校高,即使我用相同的图形大小绘制了图表,它们看起来只是大小不同

下面的两所学校就是一个例子,一所有10个年级,另一所有11个年级,所以下面的图表看起来比上面的要大

[enter image description here

我的理想结果如下:

[enter image description here

箱子宽度是否受到影响并不重要。我只希望这组图有相同的边距。你知道吗

我的代码如下(我对每个步骤都加了注释,这样您就可以跳过不相关的行):

def plot_stacked(df, **kwargs):

n_ind = len(df.index)

figsize = (20.82, 10.57) # image oupput size in unit of 100 px, eg. 20.82 will output 2082px
img_width = 2082 # just for leftside and rightside variable caculation
bar_width = 120

fig = plt.figure(figsize=figsize)
axe = fig.add_subplot(111)


"""set color for different bars"""
# color_set = ['#b9d3f1', '#6da9dc', '#e5e5e5', '#BABABA'] 
color_set = ['#b9d3f1', '#6da9dc', '#e5e5e5', '#cccccc']

#set defaults for size and font
# infoFont = r"C:\Windows\Fonts\calibri.ttf"
Fontsize = 40
fontfamily = 'Arial'
fontcolor = '#4d4d4d' # dark grey
color_text = '#58585a' #(88, 88, 90) Hex code: 58585a OLD Hex code: 4A4646
colorBackground = 'white'

axe = df.plot(kind="bar",
            figsize=figsize,
            linewidth= 0,
            stacked=True,
            color= color_set,
            legend=False,
            grid=False,
            ax=axe,

            # width= bar_width/180.0,
            **kwargs)  # make bar plots


"""loop through to get total value of proficient and advanced percentage in CORRECT order"""
internal_counter= -0.2 # set as X position of annotate numbers
for index, row in df.iterrows():
    value_list = df.loc[index].tolist()
    # print value_list 
    if len(value_list):
        if value_list[1] > 10: 
            axe.annotate(str(value_list[1]),  xy = (internal_counter, value_list[1]/2 + value_list[0] - 4), fontsize=bar_width/3.5,  family=fontfamily, color=fontcolor) # top
        if value_list[0] > 10:
            axe.annotate(str(value_list[0]),  xy = (internal_counter, value_list[0]/2.8), fontsize=bar_width/3.5,  family=fontfamily, color=fontcolor) #3rd
        if abs(value_list[2]) > 10:
            axe.annotate(str(value_list[2] * (-1)),  xy = (internal_counter, value_list[2]/2 - 4), fontsize=bar_width/3.5,  family=fontfamily, color=fontcolor) # 2nd
        if abs(value_list[3]) > 10:
            axe.annotate(str(value_list[3] * (-1)),  xy = (internal_counter, value_list[2] + value_list[3]/2 - 4), fontsize=bar_width/3.5,  family=fontfamily, color=fontcolor) # bottom
        internal_counter += 1

"""rotate x-axix value, and set position""" #grades
old_index_values = df.index.values
new_index_values = map(lambda s: s.strip(), old_index_values) # Manuuly modify x axis text to make it center
axe.set_xticklabels(new_index_values, y=0, rotation = 0, ha='center', multialignment= 'center', family=fontfamily, fontsize=bar_width/3.5, color=fontcolor)

"""set top, left and right frame invisible"""
axe.spines['left'].set_visible(False)
axe.spines['right'].set_visible(False)
axe.spines['top'].set_visible(False)
axe.spines['bottom'].set_visible(False)
axe.yaxis.set_visible(False)
axe.xaxis.set_visible(True)

"""remove the small tick lines"""
for tic in axe.xaxis.get_major_ticks():
    tic.tick1On = tic.tick2On = False

"""set background color"""
axe.set_axis_bgcolor(colorBackground)

"""set distance between text and axis"""
axe.tick_params(axis='x', which='major', pad=10)

"""set x axis text align position"""
# leftside = (-1)*(img_width*5.0/((n_col+1)*bar_width)-n_ind/2.0) # get left side value by variables. Constants are ARBETRARY.
# rightside = (-1)*leftside + n_ind - 0.8
# leftside = (-100)*(img_width/((n_ind+1)*(n_ind+1)*bar_width))
leftside = (-0.0075)*(img_width-(n_ind*190)-50)/2 -n_ind*0.15
rightside = (-1)*leftside + n_ind - 1
axe.set_xlim([leftside, rightside])

axe.set_ylim(-90,100)

"""add horizontal line at y=0"""
plt.axhline(y=0, color=fontcolor)

fig.tight_layout()
return axe



def graph_output_subtest(output_path, meta, df):
"""
get new_dataframe with final cleaned data
print out graph to output_path
resource: http://pandas.pydata.org/pandas-docs/version/0.18.1/visualization.html
"""
print '*'*10, 'Graphs for ', meta, '*'*10
graph = plot_stacked(df)
# graph.set_ylim(-105,1)
fig = graph.get_figure()
fig.savefig(output_path+"\\MAP R "+meta+".png")
plt.close(fig)
# Possible formats: eps, jpeg, jpg, pdf, pgf, png, ps, raw, rgba, svg, svgz, tif, tiff

ef graph_output(Region_ID):
"""
Print graphs of all subtest for region
"""
raw_data = get_region_lvl_MAP(Region_ID) # get raw school level data
# print raw_data

"""get region name for file name"""
region_name = list(set(raw_data['Region_Name'][raw_data['Region_ID'] == Region_ID].tolist()))
if len(region_name) != 1:
    print 'More than one name or no name found for school id:', Region_ID
else:
    region_name = region_name[0]#.replace(' ', '_')

"""get subtest list"""
# subtest_id_list = list(set(raw_data['Sub_Test_ID'][raw_data['Region_ID'] == Region_ID].tolist()))
subtest_name_list = ['Math', 'Reading']

"""loop through subtest ids"""
for subtest in subtest_name_list:
    """get real subtest name for file name printing"""
    # if subtest == 753: subtest_name = 'Reading' 
    # elif subtest ==725 : subtest_name = 'Math' 
    # else: subtest_name = 'Unknown'
    subtest_name = subtest

    meta = str(Region_ID) + ' ' + str(region_name) + ' ' + str(subtest_name) # for file name's purpose
    # print 'subtest id:', subtest
    df = format_data(raw_data, subtest) # get sub-dataframe for different levels with specific subtest type
    if not df.empty:
        graph_output_subtest(output_path, meta, df) # print and save graphs


for region in region_list:
graph_output(region)

区域是这样的:

enter image description here

任何建议都会有帮助,提前谢谢!你知道吗


Tags: namedfforoutputdatagetvaluebar
2条回答

用下面的代码我可以重现你的错误。你知道吗

import pandas as pd
import matplotlib.pyplot as plt


for k in range(8,10):

    lablist=[j for j in range(k)]
    vallist=[j for j in range(k)]
    df = pd.DataFrame({'lab':lablist, 'val':vallist})
    img_width=1540
    n_ind=len(vallist)
    leftside = (-0.0075)*(img_width-(n_ind*190)-50)/2 -n_ind*0.15
    rightside = (-1)*leftside + n_ind - 1
    ax = df.plot.bar(x='lab', y='val', rot=0,figsize=(10,5))
    ax.set_xlim([leftside, rightside])

enter image description hereenter image description here

错误驻留在^ {}和^ {}计算中,当条数改变您试图添加的空白空间不一致时。通过获取x轴的最小值和最大值并添加一个恒定的间隙,可以对齐绘图的所有条

for k in range(8,10):

    lablist=[j for j in range(k)]
    vallist=[j for j in range(k)]
    df = pd.DataFrame({'lab':lablist, 'val':vallist})
    leftside = df['lab'].min()-0.75
    rightside = df['lab'].max()+0.75
    ax = df.plot.bar(x='lab', y='val', rot=0,figsize=(10,5))
    ax.set_xlim([leftside, rightside])

enter image description hereenter image description here

希望有帮助

既然您使用了matplotlib,您是否尝试了以下方法?你知道吗

plt.rcParams["figure.figsize"] = [16,9]

如果定义了:

import matplotlib.pyplot as plt

另一方面,有几点建议:

  • 提供一个开箱即用的代码
  • 同时提供所需的输入,例如您需要的df

两者都有,你会得到更好更快的答案;)

相关问题 更多 >