Keep the gap between two datasets in matplotlib - python

I have two datasets
firstX = [0, 1, 2, 3, 4, 5, 6] # X Axis
firstY = [10, 10, 20, 30, 40, 60, 70] # Y Axis
secondX = [9, 10, 11, 12, 13, 14, 15] # X Axis
secondY = [40, 20, 60, 11, 77, 12, 54] # Y Axis
I want to plot these two datasets in the same chart but without connecting them together. As you can see, there is a disconnection between them (in X axis, 7 and 8 are missing). When I concat them, matplotlib will try to connect the last point of the first dataset (6, 70) with the first point of the second dataset (9, 40). I would like to know how to avoid this behavior

You can just plot them individually. If they're sublists of a list, e.g. X = [[X1], [X2]], Y = [[Y1], [Y2]], you can loop over them.
import matplotlib.pyplot as plt
fig = plt.figure()
for i in range(len(X)):
plt.plot(X[i], Y[i])
plt.show()

Instead of concatenating the datasets, you can call the plot command two times, plotting two times to the same axes:
import matplotlib.pyplot as plt
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot(firstX, firstY)
ax.plot(secondX, secondY)

From what I understand your question, this should work:
import matplotlib.pyplot as plt
plt.figure()
plt.plot(firstX, firstY, c='b')
plt.plot(secondX, secondY, c='b')
plt.show

Related

How to create a figure of subplots of grouped bar charts in python

I want to combine multiple grouped bar charts into one figure, as the image below shows.
grouped bar charts in a single figure
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
labels = ['G1', 'G2', 'G3']
yesterday_test1_mean = [20, 12, 23]
yesterday_test2_mean = [21, 14, 25]
today_test1_mean = [18, 10, 12]
today_test2_mean = [13, 13, 9]
Firstly I created each grouped bar chart by plt.subplots()
x = np.arange(len(labels))
width = 0.3
fig1, ax = plt.subplots()
rects1 = ax.bar(x-width/2, yesterday_test1_mean, width)
rects2 = ax.bar(x+width/2, yesterday_test2_mean, width)
fig2, ax = plt.subplots()
rects3 = ax.bar(x-width/2, today_test1_mean, width)
rects4 = ax.bar(x+width/2, today_test2_mean, width)
Then, I used add_subplot in an attempt to treat fig1 and fig2 as new axes in a new figure.
fig_all = plt.figure()
fig1 = fig_all.add_subplot(1,2,1)
fig2 = fig_all.add_subplot(1,2,2)
fig_all.tight_layout()
plt.show()
But it didn't work. How can I combined several grouped bar charts into a single figure?
Thanks in advance.
Well, I tried something. Here's a rough result. Only thing I changed is that rather using axes, I am just using subplot as I learned over time. So with fig and axes as output, there must be a way too. But this is all I've ever used. I've not added the legend and title yet, but I guess you can try it on your own too.
Here's the code with just small change:
import matplotlib.pyplot as plt
import numpy as np
labels = ['G1', 'G2', 'G3']
yesterday_test1_mean = [20, 12, 23]
yesterday_test2_mean = [21, 14, 25]
today_test1_mean = [18, 10, 12]
today_test2_mean = [13, 13, 9]
x = np.arange(len(labels))
width = 0.3
plt.figure(figsize=(12,5))
plt.subplot(121)
plt.bar(x-width/2, yesterday_test1_mean, width)
plt.bar(x+width/2, yesterday_test2_mean, width)
plt.subplot(122)
plt.bar(x-width/2, today_test1_mean, width)
plt.bar(x+width/2, today_test2_mean, width)
plt.show()
And here's your initial result:
While you see the result and try some stuff on your own, let me try to add the labels and legend to it as well as you've provided in the sample image.
Edit: The final output
So here it is, the exact thing you're looking for:
Code:
import matplotlib.pyplot as plt
import numpy as np
labels = ['G1', 'G2', 'G3']
yesterday_test1_mean = [20, 12, 23]
yesterday_test2_mean = [21, 14, 25]
today_test1_mean = [18, 10, 12]
today_test2_mean = [13, 13, 9]
x = np.arange(len(labels))
width = 0.3
plt.figure(figsize=(12,5))
plt.subplot(121)
plt.title('Yesterday', fontsize=18)
plt.bar(x-width/2, yesterday_test1_mean, width, label='test1', hatch='//', color=np.array((199, 66, 92))/255)
plt.bar(x+width/2, yesterday_test2_mean, width, label='test2', color=np.array((240, 140, 58))/255)
plt.xticks([0,1,2], labels, fontsize=15)
plt.subplot(122)
plt.title('Today', fontsize=18)
plt.bar(x-width/2, today_test1_mean, width, hatch='//', color=np.array((199, 66, 92))/255)
plt.bar(x+width/2, today_test2_mean, width, color=np.array((240, 140, 58))/255)
plt.xticks([0,1,2], labels, fontsize=15)
plt.figlegend(loc='upper right', ncol=1, labelspacing=0.5, fontsize=14, bbox_to_anchor=(1.11, 0.9))
plt.tight_layout(w_pad=6)
plt.show()
There is two method for doing subplots that you might try to combine accidentally: plt.subplot and plt.subplots.
Here is example how you can use plt.subplots to create two bar charts.
import numpy as np
import matplotlib.pyplot as plt
labels = ['G1', 'G2', 'G3']
yesterday_test1_mean = [20, 12, 23]
yesterday_test2_mean = [21, 14, 25]
today_test1_mean = [18, 10, 12]
today_test2_mean = [13, 13, 9]
x = np.arange(len(labels))
width = 0.3
fig, (ax1, ax2) = plt.subplots(1, 2)
ax1.bar(x-width/2, yesterday_test1_mean, width)
ax1.bar(x+width/2, yesterday_test2_mean, width)
ax2.bar(x-width/2, today_test1_mean, width)
ax2.bar(x+width/2, today_test2_mean, width)
plt.show()
There is only little changes on your code. You can add labels with:
ax1.set_title('Yesterday')
ax2.set_title('Today')
ax1.set_xticks(x)
ax1.set_xticklabels(labels)
ax2.set_xticks(x)
ax2.set_xticklabels(labels)

How to get arithmetically growing minor ticks with matplotlib?

The following snippet creates a list myHLines of (y) values that is arithmetically growing.
I want to use them as minor y ticks in a matplotlib plot.
How can I do this?
import matplotlib.pyplot as plt
import pandas as pd
df = pd.DataFrame({'a': [1, 3, 10, 30, 100]})
myMin = df.a.min()
myMax = df.a.max()
ratio = 3
myHLines = [myMin * ratio ** i for i in range(1000) if myMin * ratio ** i < myMax]
print("myHLines=", myHLines)
# myHLines= [1, 3, 9, 27, 81]
plt.plot(df, '-o', markersize=2, c='r')
plt.show()
Is the scale of the y-axis you want to achieve the y-axis shown in the graph below?
plt.plot(df, '-o', markersize=2, c='r')
locs, labels = plt.yticks()
new_y = sorted(myHLines + locs.tolist()[1:-1])
# print(new_y)
plt.yticks(new_y)
plt.show()

Got more ylabels than specified by set_yticklabel() [duplicate]

Here is a simple plot:
1) How to disable the ticks?
2) How to reduce their number?
Here is a sample code:
from pylab import *
import numpy as np
x = [5e-05, 5e-06, 5e-07, 5e-08, 5e-09, 5e-10]
y = [-13, 14, 100, 120, 105, 93]
def myfunc(x,p):
sl,yt,yb,ec=p
y = yb + (yt-yb)/(1+np.power(10, sl*(np.log10(x)-np.log10(ec))))
return y
xp = np.power(10, np.linspace(np.log10(min(x)/10), np.log10(max(x)*10), 100))
pxp=myfunc(xp, [1,100,0,1e-6])
subplot(111,axisbg="#dfdfdf")
plt.plot(x, y, '.', xp, pxp, 'g-', linewidth=1)
plt.xscale('log')
plt.grid(True,ls="-", linewidth=0.4, color="#ffffff", alpha=0.5)
plt.draw()
plt.show()
Which produces:
plt.minorticks_off()
Turns em off!
To change the number of them/position them, you can use the subsx parameter. like this:
plt.xscale('log', subsx=[2, 3, 4, 5, 6, 7, 8, 9])
From the docs:
subsx/subsy: Where to place the subticks between each major tick.
Should be a sequence of integers. For example, in a log10 scale: [2,
3, 4, 5, 6, 7, 8, 9]
will place 8 logarithmically spaced minor ticks between each major
tick.
Calling plt.minorticks_off() will apply this to the current axis. (The function is actually a wrapper to gca().minorticks_off().)
You can also apply this to an individual axis in the same way:
import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.minorticks_off()
from pylab import *
import numpy as np
x = [5e-05, 5e-06, 5e-07, 5e-08, 5e-09, 5e-10]
y = [-13, 14, 100, 120, 105, 93]
def myfunc(x,p):
sl,yt,yb,ec=p
y = yb + (yt-yb)/(1+np.power(10, sl*(np.log10(x)-np.log10(ec))))
return y
xp = np.power(10, np.linspace(np.log10(min(x)/10), np.log10(max(x)*10), 100))
pxp=myfunc(xp, [1,100,0,1e-6])
ax=subplot(111,axisbg="#dfdfdf")
plt.plot(x, y, '.', xp, pxp, 'g-', linewidth=1)
plt.xscale('log')
plt.grid(True,ls="-", linewidth=0.4, color="#ffffff", alpha=0.5)
plt.minorticks_off() # turns off minor ticks
plt.draw()
plt.show()

Plot a histogram using Python with manual bins

I am trying to plot a histogram using the matplotlib.hist() function.
Below code is not getting the correct histogram
X axis is the years (age), X axis I want to have 0 20, 25, 30, 35, 40, 45, 50, 55
Y axis is the probability
Someone can help me to get the correct histogram ?
import matplotlib.pyplot as plt
list_age = ['26','28','26','36','38','31','22','31','25','30','37','27','27','29','27','21','27','38','31','41','28','31','28','33','26','39','37','24','31','34','39','33','22', '30','24','29','28','34','27','28','26','26','25','40','24','37','24','28','26','29','26','31','23','31','36','32','25','31','25','33','36','27','28',
'25','27','39','36','30','31','34','23','31','32','31','33','32','39','35','35','22','34','25','35','35','41','20','21','35','32','30','22','21','23','33','25','30','24','39','24','27','22','33','30','27','30','23','29','30','22','31','29','31','24','29','25','24','26','29','31','24','32','21','25','29','30']
list_age.sort()
bins = 55
plt.hist(list_age, bins, facecolor='g')
plt.xlabel('Years')
plt.ylabel('Probability')
plt.grid(True)
plt.show()
You need to convert your list_age to a list of integers first (instead of a list of strings).
Then, simply use the options density (or normed) to display probability and xticks to change the ticks for the x-axis.
import matplotlib.pyplot as plt
list_age = ['26','28','26','36','38','31','22','31','25','30','37','27','27','29','27','21','27','38','31','41','28','31','28','33','26','39','37','24','31','34','39','33','22', '30','24','29','28','34','27','28','26','26','25','40','24','37','24','28','26','29','26','31','23','31','36','32','25','31','25','33','36','27','28',
'25','27','39','36','30','31','34','23','31','32','31','33','32','39','35','35','22','34','25','35','35','41','20','21','35','32','30','22','21','23','33','25','30','24','39','24','27','22','33','30','27','30','23','29','30','22','31','29','31','24','29','25','24','26','29','31','24','32','21','25','29','30']
list_age = [ int(i) for i in list_age ]
bins = len(set(list_age))
plt.hist(list_age, bins = bins, density = True, facecolor = "g") # Replace density by normed if older version of matplotlib
plt.xticks(range(0, 55, 5))
plt.xlabel('Years')
plt.ylabel('Probability')
plt.grid(True)
plt.show()
If you want to display the bars at specific bins, simply define bins at their coordinates:
plt.hist(list_age, bins = [ 0, 20, 25, 30, 35, 40, 45, 50, 55 ], density = True, facecolor = "g")

How to update a plot or graph in matplotlib

I would like to know how to update a graph and or plot in matplotlib every few seconds. Code:
import matplotlib.pyplot as plt
import numpy as np
axes = plt.gca()
axes.set_xlim([0,5])
axes.set_ylim([0,100])
X = [0, 1, 2, 3, 4, 5]
Y = [15, 30, 45, 60, 75, 90]
plt.plot(X, Y)
plt.xlabel('Time spent studying (hours)')
plt.ylabel('Score (percentage)')
plt.show()
What you have written is correct , but in order to make your code dynamic , you can put the code in a function and pass the X and Y coordinates to the function . One example as shown below
def GrapgPlot(X, Y):
"Your code"
GrapgPlot([0, 1, 2, 3, 4, 5],[90, 30, 45, 60, 75, 90])
In the plot if you are certain that X axis will not change than you can fix X axis in the code and take only Y axis values as a list from the user as an input and pass it in the function as an argument.
else the best way if you do want user interaction . Update the X and Y axis list with a loop and pass X and Y values in the function as an argument
Used time.sleep(1) for being able to see the changes and reversed Y for new data to be updated. Hopefully this is what you want:
%matplotlib notebook
import time
import matplotlib.pyplot as plt
X = [0, 1, 2, 3, 4, 5]
Y = [15, 30, 45, 60, 75, 90]
fig, ax = plt.subplots()
ax.set_xlim([0,5])
ax.set_ylim([0,100])
ax.set_xlabel('Time spent studying (hours)')
ax.set_ylabel('Score (percentage)')
l, = ax.plot(X, Y)
for ydata in [Y, Y[::-1]]*2:
l.set_ydata(ydata)
fig.canvas.draw()
time.sleep(0.5)

Categories