Plotting a Bar Graph in python with Matplotlib.pyplot - python

Groups Counts
1 0-9 38
3 10-19 41
5 20-29 77
7 30-39 73
9 40-49 34
I want to create a bar graph using matplotlib.pyplot library with groups on x-axis and Counts on y-axis. I tried it out using following code
ax = plt.subplots()
rects1 = ax.bar(survived_df["Groups"], survived_df["Counts"], color='r')
plt.show()
but I'm getting following error
invalid literal for float(): 0-9

The first array given to the plt.bar function must be numbers corresponding to the x coordinates of the left sides of the bars. In your case, [0-9, 10-19, ...] is not recognized as valid argument.
You can however make the bar plot using the index of your DataFrame, then defining the position of your x-ticks (where you want your label to be positioned on the x axis) and then changing the labels of your x ticks with your Groups name.
fig,ax = plt.subplots()
ax.bar(survived_df.index, survived_df.Counts, width=0.8, color='r')
ax.set_xticks(survived_df.index+0.4) # set the x ticks to be at the middle of each bar since the width of each bar is 0.8
ax.set_xticklabels(survived_df.Groups) #replace the name of the x ticks with your Groups name
plt.show()
Note that you can also use the Pandas plotting capabilities directly with a one liner:
survived_df.plot('Groups', 'Counts', kind='bar', color='r')

Related

Shift plots of different lengths in the same x-axis

I have a very specific something I want to do with matplotlib I don't even know if it's possible, but I figured it was worth asking. Maybe the answers will give me an alternate idea about how to go about it.
I have 4 arrays of similar, but different lengths that I want to plot in the same x-axis. This question suggests creating the values for x using range(), and it worked:
plt.figure(figsize=(8, 6), dpi=300)
x_5 = range(len(all_data_float[0]))
plt.plot(x_5, all_data_float[0], color='b', marker='.')
x_10 = range(len(all_data_float[1]))
plt.plot(x_10, all_data_float[1], color='r', marker='.')
x_15 = range(len(all_data_float[2]))
plt.plot(x_15, all_data_float[2], color='g', marker='.')
x_20 = range(len(all_data_float[3]))
plt.plot(x_20, all_data_float[3], color='c', marker='.')
plt.show()
But I wanted to do something else, I want to plot a vertical line in the middle aligned by a point, for example there are 4 plots with:
plot1: 101 points
plot2: 99 points
plot3: 100 points
plot4: 101 points
So for plot1, that point would be index 51, which means 51 points before and 49 after with the line crossing point 51. For plot2, that middle point is index 49, which means 49 points before and 50 after, and so forth.
My difficulty is that the vertical line has a different index for each plot. I know plt.vlines() accepts an array, but in this case it plots multiple lines, and I wanted a single line.
Is there a way to "shift" each plot relative to the x-axis? so index 51 of plot1 aligns with index 49 of plot2, etc? Or is there a better strategy to do this?
From the set up of the question I am going to assume that the the x-values do not have any numerical meaning so it is safe from a data-point-of-view to shift them around. Instead of plotting your data against range(len(...)), do the shift there!
import matpoltlib.pyplot as plt
import numpy as np
def synthetic_data(length):
"make some variable length synthetic data to plot."
return np.exp(-((np.linspace(-5, 5, length)) ** 2))
data = [synthetic_data(51), synthetic_data(75), synthetic_data(105)]
fig, ax = plt.subplots(constrained_layout=True)
for d in data:
x_vector = np.arange(len(d)) - len(d) // 2
ax.plot(x_vector, d)
ax.axvline(0, color="k", ls="--")
ax.set_xlabel("delta from center")
ax.set_ylabel("synthetic data!")

How to shift yaxis ( or axis ) tick labels at a required position in Matplotlib?

Consider this matrix (matG) for which I am trying to make a heatmap
48 12 6 13
12 48 12 36
6 12 54 14
13 36 14 84
Since it is a symmetric matrix so I need only triangular heatmap, masking the upper triangle data of the matrix.
import seaborn as sns
import matplotlib.pyplot as plt
plt.xticks(fontsize=12,weight='bold')
**plt.yticks(fontsize=12,weight='bold',ha='right') #trying to shift the ticklabel text**
mask = np.triu(np.ones_like(matG.T, dtype=bool))
cmap = sns.color_palette('OrRd')
labl2 = ['Class1','Class2','Class3','Class4']
ax = sns.heatmap(matG,mask=mask,cmap=cmap,center=0,cbar=False,square=True, linewidths=.5,
cbar_kws={"shrink": .5},xticklabels=labl2,yticklabels=labl2,annot=True,fmt='g')
ax.get_xticklabels()[3].set_visible(False); ax.get_yticklabels()[0].set_visible(False)
ax.xaxis.get_majorticklines()[3].set_visible(False); ax.yaxis.get_majorticklines()[0].set_visible(False)
**for tick in ax.get_yticklabels():
x,y = tick.get_position()
tick.set_position((x,y+44))**
ax.xaxis.set_label_coords(0.35,-0.1)
ax.tick_params(axis='x', labelrotation=45)
This gives me the following plot:
But the problem is, as you can see in the picture, the y-axis tick labels are not in the center. I have shown by an arrow that the text needs to be shifted upwards.
In the code, I have made the relevant syntax above bold using which I tried to bring the tick labels to the center of the tick and make it look symmetric. But it is not happening. Any suggestions, please? Thank you
You can center y-tick labels vertically with:
ax.set_yticklabels(['Class2','Class3','Class4'], va='center')
OR
ax.set_yticklabels(labl2[1:], va='center')
You have used 'ha', instead use 'va':
plt.yticks(fontsize=12,weight='bold',va='center')

matplotlib set_major_formatter creating 2 plots

This excerpt from my code changes the value of the y axis labels from exponential to millions. Problem is it creates 2 figures. The first one is an x and y axis with no plot (and the scale of the x axis is used for the y axis as well), and then the 2nd figure is exactly what I want. It is a double bar graph.
I am guessing it has something to do with using f.plot.bar instead of plt.bar but I am not sure. I just want to get rid of the first figure than all will be well.
from matplotlib.ticker import FuncFormatter
def millions(x, pos):
'The two args are the value and tick position'
return '%1.1fM' % (x*1e-6)
formatter = FuncFormatter(millions)
fig, ax = plt.subplots()
ax = tempg.plot.bar(y=['Republican2016Votes', 'Democrat2016Votes'], rot=0,
color = ['DarkRed','Blue'])
ax.yaxis.set_major_formatter(formatter)
plt.show()

Graph layout issues Matplolib python 3

Basically, I'm plotting a graph based on a list of times(HH:MM:SS, x-axis) and float values (y-axis) stored in a txt file like this:
15 52 27 0.00
15 52 37 0.2
15 52 50 0.00
15 53 12 2.55
15 54 21 10.00
15 55 15 13.55
I want to plot the last float values (as an annotation text label) in correspondence of the last time available. Using the txt above, I want to plot "13.55 mL" in correspondence of the point [15 55 15, 13.55].
Here's the code to plot my graph:
datefunc = lambda x: mdates.date2num(datetime.strptime(x.decode("utf-8"), '%H %M %S'))
dates, levels = np.genfromtxt('sensor1Text.txt', # Data to be read
delimiter=8, # First column is 8 characters wide
converters={0: datefunc}, # Formatting of column 0
dtype=float, # All values are floats
unpack=True) # Unpack to several variables
# Configure x-ticks
plot_fs1.set_xticks(dates) # Tickmark + label at every plotted point
plot_fs1.xaxis.set_major_formatter(mdates.DateFormatter('%H:%M:%S'))
plot_fs1.set_ylabel('Fluid (mL)')
plot_fs1.grid(True)
# Format the x-axis for dates (label formatting, rotation)
fs1.autofmt_xdate(rotation= 45)
plot_fs1.plot_date(dates, levels, color='orange', ls='-', marker='o')
Here's my attempt to plot the annotation label on my last plotted value:
lastxValue= len(dates)-1
lastyValue= len(levels)-1
lastValue = levels[lastyValue]
lastDate = dates[lastxValue]
plot_fs1.annotate(lastValue, (lastDate,
lastValue),xytext=(15, 15),textcoords='offset points')
fs1.tight_layout()
This is what I get:
The annotation is not completely displayed within the plot window and x-axis values tend to overlap on one another.
Any thoughts?
To avoid having x-axis entries for every point you plot, you could use a locator to just mark for example every minute on your graph.
Secondly, avoid using tight_layout() and instead make use of subplots_adjust() to add additional spacing where you need it. For example:
import numpy as np
import matplotlib
import matplotlib.dates as mdates
import matplotlib.pyplot as plt
datefunc = lambda x: mdates.date2num(datetime.strptime(x.decode("utf-8"), '%H %M %S'))
dates, levels = np.genfromtxt('sensor1Text.txt', # Data to be read
delimiter=8, # First column is 8 characters wide
converters={0: datefunc}, # Formatting of column 0
dtype=float, # All values are floats
unpack=True) # Unpack to several variables
plot_fs1 = plt.gca()
fig = plt.gcf()
p = plt.plot(dates, levels)
plot_fs1.set_xticks(dates) # Tickmark + label at every plotted point
plot_fs1.xaxis.set_major_formatter(mdates.DateFormatter('%H:%M'))
plot_fs1.xaxis.set_major_locator(matplotlib.dates.MinuteLocator())
plot_fs1.set_ylabel('Fluid (mL)')
plot_fs1.grid(True)
fig.autofmt_xdate(rotation= 45)
plot_fs1.plot_date(dates, levels, color='orange', ls='-', marker='o')
lastxValue = len(dates)-1
lastyValue = len(levels)-1
lastValue = levels[lastyValue]
lastDate = dates[lastxValue]
plot_fs1.annotate("{} mL".format(lastValue), (lastDate, lastValue), xytext=(15, 15), textcoords='offset points')
fig.subplots_adjust(bottom=0.15, right=0.85) # Add space at bottom and right
plt.show()
This would give you a graph looking:
One option is use a similar approach as this question and have independent and linear spaced xticks and use dates just as the name of the ticks.
That question uses bars, but you can use your difference in seconds and see how much total time you have passed, make your tick spacing in order to cover the whole time, but with the same step. Your time difference (that has difference spacing) you just need in the plot of your points. The xticks get nicer with a proper spacing. It also help to add an extra space that you need for your text.

matplotlib xticks not being assigned for 0

I am writing a code in python to map 30 values to a list of (0,1,2,.......29) using matplotlib.
Later i want to use xticks to give specific names for the x axis values from 0 to 29.
However when i use the matplotlib.pyplot.xticks method,my origin is left as it was and the name I assigned for 0 appears in place of 1 and so on until 29th item in the list. And after that for the 30th item,(i.e the name to be assigned for 29) appears at the end with no point corresponding to it.
Can anybody help me solve this problem?
I usually go with the set_xticklabels method for axis objects, e.g.
import matplotlib.pyplot as plt
x = range(10)
y = range(10)
labels = ['super long axis label' for i in range(10)]
fig, ax = plt.subplots()
plt.plot(x, y)
# set custom tick labels
ax.set_xticklabels(labels, rotation=45, horizontalalignment='right')
plt.show()

Categories

Resources