user13820515
user13820515

Reputation:

How can I plot side by side bars along X axis using CSV data

I'm trying to create a bar graph with 2 bars on one X axis tick(date) that represents two sets of data. However, I'm not able to make it span across the the graph to other x axis ticks.

Here is my code:

simsubs = pd.read_csv('simsubs.csv')

fig, axs = plt.subplots(4, sharex=True, figsize=(11,9))

bar_width = 0.35

x = simsubs.Date

axs[3].bar(x, simsubs['CPS1 Deletes'], width=bar_width, zorder=2, label='Deletes', color='#A31214')
axs[3].bar(bar_width, simsubs['CPS1 Total'], width=bar_width, zorder=2, label='Deletes', color='blue')

plt.xticks(rotation=45)

plt.show()

simsubs.Date points to dates in my CSV that I would like plotted along the X axis but this is the img my code produces:

Image

Thanks in advance for any help. I'm new to the community and python coding in general, apologies if my terminology or my post might be confusing.

Upvotes: 1

Views: 205

Answers (2)

busybear
busybear

Reputation: 10590

You need to create your bar graphs on the same scale. An easy way is to create x values that simply count the data and offset them appropriately. You can label the x axis with set_xticklabels if you want.

X = np.arange(len(x))
bar_width = 0.25
offset = bar_width / 2

axs[3].bar(X - offset, simsubs['CPS1 Deletes'], width=bar_width, color='#A31214')
axs[3].bar(X + offset, simsubs['CPS1 Total'], width=bar_width, color='blue')
axs[3].set_xticks(X)
axs[3].set_xticklabels(x)

Also having zorder and label the same for both calls to bar defeats their intended use if these are the only data you are plotting.


Alternatively, you can use pandas plotting:

simsubs[['CPS1 Deletes', 'CPS1 Total']].plot.bar()

Upvotes: 1

dm2
dm2

Reputation: 4275

axs[3].bar(bar_width, simsubs['CPS1 Total'], width=bar_width, zorder=2, label='Deletes', color='blue')

Here your x value is stationary, i.e. all data is plotted on x = bar_width = 0.35. You should change bar_width to x + bar_width (i.e. offset x position of second bar plot by bar_width from the first one) so it looks like this:

axs[3].bar(x + bar_width, simsubs['CPS1 Total'], width=bar_width, zorder=2, label='Deletes', color='blue')

Edit:

Seeing as your x values are Timestamps, I manage to do what you're looking for by first changing those Timestamp values to pandas DateTime object as:

simsubs['Date'] = simsubs['Date'].apply(pd.to_datetime)

then applying an offset which you would have to adjust as:

x_offset = simsubs['Date'] + pd.Timedelta(offset, units)

This should work as your X values are evenly distributed (7 days apart) and so I would suggest offset = 3.5 and units = 'days'. Use this x_offset as x value in your second bar plot.

I've tried resetting these DateTime objects to TimeStamps (in case dates are NOT evenly distributed, it looks better with TimeStamps), but plotting keeps messing up for me.

Upvotes: 0

Related Questions