简体   繁体   中英

How to centre line graph with bar graph in MatPlotLib?

My Problem:

I am havinging difficutly trying to get my line graph to centered with the y ticks. Currently there seems to be an offset to the left when I draw my graphs. Also I am having difficulty in trying to get both of the labels to appear in the same legend.

My Code:

f, ax1 = plt.subplots(1, figsize=(10, 5))

# Set the bar width
bar_width_tram = 1
bar_width_brake_percentage = 1

# Positions of the left bar-boundaries
bar_l = [i + 1 for i in range(len(data_frame['Tram Hrs']))]

# Positions of the x-axis ticks (center of the bars as bar labels)
tick_pos = [i + (bar_width_tram / 2) for i in bar_l]

# Define the colours for the corresponding
# bars in the graph
tram_data_hrs_colour = '#00AC00'   # Green
bd_per_colour = '#DA0505'   # Red

# Create a bar plot, in position bar_1
ax1.bar(bar_l,
        # using the pre_score data
        data_frame['Tram Hrs'],
        # get rid of border lines
        edgecolor="none",
        # set the width
        width=bar_width_tram,
        # with the label pre score
        label='Tramming Hours',
        # with alpha 0.5
        alpha=0.05,
        # with color
        color=tram_data_hrs_colour)


    # Set the X-ticks with dates
    plt.xticks(tick_pos, data_frame['Date'])

    plt.yticks(np.arange(0, 15, 3))

    # Set the labels and legend
    ax1.set_ylabel("Tramming Time (Hours)")
    ax1.set_xlabel("Previous Week")

    # Second axis
    ax2 = ax1.twinx()
    ax2.set_ylabel("Braking to Tramming  (%)")

    plt.plot(bar_l,data_frame['Brake%'], '-', label='Relative Braking Percentage')

    plt.yticks(np.arange(0, 250, 50))

    # Set the title of the chart
    plt.legend(loc='upper left')

Above Code Outputs: 在此处输入图片说明

My Questions:

Q1. How can I get the line graph to be centred/aligned with the x-tics in the bar graphs along the x-axis (iecurrently they are left biased)?

Q2. How can I get both of the labels to appear in the legend?

My Ideal Output: 在此处输入图片说明

Data:

  Date  Brake Hrs  Tram Hrs  Brake%  Tram%  Br/Tr%
0  Mon       0.87      4.26   16.90  83.10   20.33
1  Tue       1.00      3.05   24.66  75.34   32.73
2  Wed       1.77      3.87   31.44  68.56   45.85
3  Thu       1.86      5.16   26.44  73.56   35.94
4  Fri       1.41      2.01   41.15  58.85   69.93
5  Sat       0.01      5.03    0.14  99.86    0.14
6  Sun       0.40      1.16   25.82  74.18   34.82

Using columns Date for x axis, and Tram Hrs axis 1, Br/Tr% for axis 2

Concerning Q1, what you need to do is to set the bar alignment, adding align = 'center' to the ax.bar call ( http://matthiaseisen.com/pp/patterns/p0177/ )

For Q2, you can follow this SO answer: Single legend for multiple axes .

Finally, I have added at the bottom a call to plt.xlim to leave white space both sides of the chart.

Please find attached below proposed solution and output obtained:

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np

cols = ['Date', 'Brake Hrs',  'Tram Hrs',  'Brake%',  'Tram%',  'Br/Tr%']
data_frame = pd.DataFrame([['Mon',       0.87,      4.26,   16.90,  83.10,   20.33],
                            ['Tue',       1.00,      3.05,   24.66,  75.34,   32.73],
                            ['Wed',       1.77,      3.87,   31.44,  68.56,   45.85],
                            ['Thu',       1.86,      5.16,   26.44,  73.56,   35.94],
                            ['Fri',       1.41,      2.01,   41.15,  58.85,   69.93],
                            ['Sat',       0.01,      5.03,    0.14,  99.86,    0.14],
                            ['Sun',       0.40,      1.16,   25.82,  74.18,   34.82]],
                         columns = cols)



f, ax1 = plt.subplots(1, figsize=(10, 5))

# Set the bar width
bar_width_tram = 1
bar_width_brake_percentage = 1

# Positions of the left bar-boundaries
bar_l = [i + 1 for i in range(len(data_frame['Tram Hrs']))]

# Positions of the x-axis ticks (center of the bars as bar labels)
tick_pos = [i + (bar_width_tram / 2) for i in bar_l]

# Define the colours for the corresponding
# bars in the graph
tram_data_hrs_colour = '#00AC00'   # Green
bd_per_colour = '#DA0505'   # Red

# Create a bar plot, in position bar_1
ax1.bar(bar_l,
        # using the pre_score data
        data_frame['Tram Hrs'],
        # get rid of border lines
        edgecolor="none",
        # set the width
        width=bar_width_tram,
        # with the label pre score
        label='Tramming Hours',
        # with alpha 0.5
        alpha=0.05,
        # with color
        color=tram_data_hrs_colour,
        align = 'center')


# Set the X-ticks with dates
plt.xticks(tick_pos, data_frame['Date'])

plt.yticks(np.arange(0, 15, 3))

# Set the labels and legend
ax1.set_ylabel("Tramming Time (Hours)")
ax1.set_xlabel("Previous Week")

# Second axis
ax2 = ax1.twinx()
ax2.set_ylabel("Braking to Tramming  (%)")

plt.plot(bar_l,data_frame['Brake%'], '-', label='Relative Braking Percentage')

plt.yticks(np.arange(0, 250, 50))

# Set the title of the chart
h1, l1 = ax1.get_legend_handles_labels()
h2, l2 = ax2.get_legend_handles_labels()
ax1.legend(h1+h2, l1+l2, loc=2)

plt.xlim(0, len(tick_pos) + 1)

在此处输入图片说明

This looks in line with your desired output. I am using matplotlib 1.5.1 and pandas 0.18.1

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM