How can I plot multiple line in the same graph in python? - python

I want to create this graph 1 in python using matplotlib. I created a list called generation that is initialized with values from 0 to 200. I created a list variable consisting of 38 lists. Each list consists of 200 float numbers. I tried to plot the data but I have the error:
ValueError: x and y must have same first dimension, but have shapes (200,) and (38,)
My code:
generation = []
for i in range(200):
generation.append(i)
plt.xlabel("X-axis")
plt.ylabel("Y-axis")
plt.title("A test graph")
for i in range(len(listt)):
#generation is a list with 200 values
#listt is a list with 38 lists
#list1 is a list with 200 values
plt.plot(generation ,[list1[i] for list1 in listt],label = 'id %s'%i)
plt.legend()
plt.show()
The final graph I want to look like the one below:
Each line in this graph 1 corresponds to a different input value. For each input, the algorithm runs 100 generations. The graph shows how the results of the algorithm evolve over 100 generations.

You're almost there! You only need to use listt[i] instead of [list1[i] for list1 in listt].
So, the code should look like this:
import matplotlib.pyplot as plt
#random listt
listt = [[i for j in range(200)] for i in range(38)]
generation = []
for i in range(200):
generation.append(i)
plt.xlabel("X-axis")
plt.ylabel("Y-axis")
plt.title("A test graph")
for i in range(len(listt)):
plt.plot(generation ,listt[i],label = 'id %s'%i) #<--- change here
plt.legend()
plt.show()
And it returns this graph:
Of course, it won't be exactly as yours since I randomly generated listt.

Related

For-Loop for a Muti-line plot in python

I would like to make a Scatter-plot using a For-Loop of heights vs widths but have each location be a separate set (each one has a different color). This is what I currently have
df = pd.read_csv(load_path +'mars_lobes.csv')
n=8
h={}
for i in range(1,n):
h["patchheight{0}".format(i)]=df.loc[df["patch"] == ("patch"+str(i)), 'height']
w={}
for i in range(1,n):
w["patchwidth{0}".format(i)]=df.loc[df["patch"] == ("patch"+str(i)), 'width']
height=list(h.values())
width=list(w.values())
plt.figure()
plt.loglog(*zip(*sorted(h.items())),*zip(*sorted(w.items())),'.',markersize=4,c='b')
plt.show()
I do this and it gives me even thou they are the same size
ValueError: setting an array element with a sequence

How do I store my results which are of the form of graphs and numerical outputs/ Is there a universal way of storing any kind of result in python?

I am writing a program that runs for a long time. I want to run this program many times so that I can see the dependence of my results on the tweaking of parameters.
So, suppose a situation similar to the following:
parameter=1
"Big code that takes a long time"
print(output, "output that depends on t")
plt.plot(x,y)
Now change the parameter to 2 and re-run again. I want to be able to pull the results of the previous one so that I can compare them.
So I want to sort of store them somehow so that the next time I need to look at the results I just have to execute a few lines and the stored results come up really quickly.
You can store all the information such as the inputs, params, and outputs in a dictionary. You can then use the dict to do further plotting and analysis.
Here I add a minimal reproducible example. You can use this as a reference for your needs. The below code produces this plot as an output.
import matplotlib.pyplot as plt
import numpy as np
import random
def big_code(param, input):
output = [i + param**(random.randrange(2, 5)) for i in input]
return output
def plot_experiments(info):
rows, cols = 1, 6
_, axs = plt.subplots(rows,cols)
i = 0
for val in info.values():
param_idx = val['param']
axs[i].plot(val['input'], val['output'])
axs[i].set_title(f'param {param_idx}')
i+=1
for ax in axs.flat:
ax.set(xlabel='x-label', ylabel='y-label')
# Hide x labels and tick labels for top plots and y ticks for right plots.
for ax in axs.flat:
ax.label_outer()
plt.show()
if __name__ == '__main__':
input_params = [1,2,3,4,5,6]
input_list = np.array(list(range(2000)))
info = {}
for exp_id ,param in enumerate(input_params):
# Run your big code to get output
output = big_code(param, input_list)
# Save your output to a dataframe
info[exp_id] = {'input': input_list, 'output': output, 'param': param }
# Access your dict and plot
plot_experiments(info)

Python and plotting the histograms (using matplotlib)

My problem in general: I have a function, that creates and saves the histograms. In my code I run the function twice: 1st time to create and save one plot with one data array, 2nd time to create and save second plot with another data array.
After the completion of the program, I get 2 .png files: the 1st one contains the histogram of one data array, the 2nd one contains histogram of the first AND the second data arrays!
What I need is one plot for one array, and second plot for another array. My mind's gonna blow, I just can't get, what's wrong here. Might somebody give me a clue?
Here's a part of my code and resulting images:
def mode(station_name, *args):
...
#before here the 'temp' data array is generated
temp_counts = {}
for t in temp:
if t not in temp_counts:
temp_counts[t] = 1
else:
temp_counts[t] += 1
print(temp_counts) **#this dictionary has DIFFERENT content being printed in two function runs**
x = []
for k, v in temp_counts.items():
x += [k for _ in range(v)]
plt.hist(x, bins="auto")
plt.grid(True)
plt.savefig('{}.png'.format(station_name))
#---------------------------------------------------------------------------------------------------
mode(station_name, [...])
mode(station_name, [...])
the 'like' of 1 image i get
the 'like' of 2 image i get
real images i get after my full script finishes #1
real images i get after my full script finishes #2
If you use plt.plotsomething.. the plot is added to the current figure in use, therefore the second histogram is added to the first. I suggest using the matplotlib object API to avoid confusion: you create figure and axis and you generate your plots starting from them. Here's your code:
def mode(station_name, *args):
...
#before here the 'temp' data array is generated
temp_counts = {}
for t in temp:
if t not in temp_counts:
temp_counts[t] = 1
else:
temp_counts[t] += 1
print(temp_counts) **#this dictionary has DIFFERENT content being printed in two function runs**
x = []
for k, v in temp_counts.items():
x += [k for _ in range(v)]
fig, ax = plt.subplots(1):
ax.hist(x, bins="auto")
ax.grid(True)
fig.savefig('{}.png'.format(station_name))
#---------------------------------------------------------------------------------------------------
mode(station_name, [...])
mode(station_name, [...])
This should do the job for you

How to use matplotlib to plot a function graph if I have 2 prepared np.arrays of points?

I provide a python-code which solves Gauss equations and plots a function graph. I have a problem in plotting my function. When I try to plot a function graph for example - "2sin(2πx)" I see lines which connect point and it isn't that i would see.
import numpy as np
import math
import random
import matplotlib.pyplot as plt
import pylab
from matplotlib import mlab
print 'case1=2sin(2πx)'
print 'case2=cos(2πx)'
print 'case3=5x^3 + x^2 + 5'
Your_function=raw_input("Enter your choise of your function: ")
def Choising_of_function(x, Your_function):
if Your_function=='case1':
return 2*math.sin(2*x*math.pi)
elif Your_function=='case2':
return math.cos(2*x*math.pi)
elif Your_function=='case3':
return 5*x**3 + x**2 + 5
Dimension_of_pol=int(raw_input("Enter your degree of polynom: "))
Points=int(raw_input("Enter number of points: "))# I just need only limited numbers of points to plot a function graph
Interval=int(raw_input("Enter interval of your points: "))
dx=float(raw_input("Enter interval your dx: "))
X_val=[]
Y_val=[]
for i in range(Points):# First, i generate my values of x
x = random.uniform(-Interval, Interval)
X_val.append(x)
for x in X_val:
y=Choising_of_function(x, Your_function)
Y_val.append(y)
print X_val, Y_val
Arr_Xo=[[x**i for i in range(Dimension_of_pol)] for x in X_val]
print Arr_Xo
D_mod={}
D={}
for y, x in zip(Y_val, X_val):
D_mod[y]=x
Arr_X_o=np.array(Arr_Xo)
print Arr_X_o
Arr_X=np.array(X_val) #My array of x-values
print Arr_X
Arr_Y=np.array(Y_val) #My array of y-values
print Arr_Y
m = np.linalg.lstsq(Arr_X_o, Arr_Y)[0]
print m
pylab.plot(Arr_X, Arr_Y, 'go')
line=plt.plot(Arr_X, Arr_Y)
line.show()
How i can plot my function without using frange.
My array of x:
[-15.9836388 13.78848867 -3.39805316 12.04429943 -12.34344464
-19.66512508 6.8480724 -5.58674018 7.59985149 11.46357551
-4.96507337 -2.40178658 -1.71320151 -12.87164233 -3.26385184
-7.44683254 5.52525074 -9.16879057 3.70939966 -4.80486815
-10.35409227 6.72283255 2.00436008 8.68484529 -17.81750773]
My array of y:
[ 0.20523902 -1.941802 -1.19527441 0.54952271 -1.66506802 1.72228361
-1.63215286 1.03684409 -1.17406016 0.45373838 0.43538662 -1.15733373
1.94677887 1.44373207 -1.99242991 -0.65576448 -0.31598064 -1.74524107
-1.9352764 1.88232214 -1.58727561 -1.97093284 0.05478352 -1.83473627
1.8227666 ]
I paste all of it in :
line=plt.plot(Arr_X, Arr_Y)
plt.show()
And my function graph doesnt looks like 2*sin(2px)
The problem is that your x axis values are not in order, therefore when you plot them your points will not be joined to the next point on the x axis, giving a graph that looks like the one in the question. A test of this will be to use plt.scatter instead of plt.plot:
This shows that the points you are generating are in the correct shape as seen in the left most image, however you are just generating the x values slightly wrong.
In order to get a nice looking graph you need to change the way you generate the x values. This can be done using np.linspace, the documentation can be found here.
# for i in range(Points): # First, i generate my values of x
# x = random.uniform(-Interval, Interval)
# X_val.append(x)
# replace the above 3 lines with the one below
X_val = np.linspace(-Interval,Interval,Points)
In addition, there is no need to assign plt.plot to a variable, therefore the last 3 lines of your code should be replaced with:
# pylab.plot(Arr_X, Arr_Y, 'go')
# line=plt.plot(Arr_X, Arr_Y)
# line.show()
# replace the above 3 lines with the one below
pylab.plot(Arr_X, Arr_Y)
plt.show()
This produces the following graph:
I do not know what the reason is to
pylab.plot(Arr_X, Arr_Y, 'go')
as well as
line=plt.plot(Arr_X, Arr_Y)
Why do you need pylab to plot instead of just using pyplot?
Your
line.show() in line 63 gives me an attribute error
"list" object has no attribute "show"
only plt has show(), if you see in print dir(plt)
As I am to lazy to go trough your full code stick to this general plotting example:
import matplotlib.pyplot as plt
figure, axis = plt.subplots(figsize=(7.6, 6.1))
for x in range(0, 500):
axis.plot(x, x*2, 'o-')
plt.show()

Matplotlib has duplicate legend entries

I'm using pylab.plot() in a for loop, and for some reason the legend has 6 entries, even though the for loop is only executed 3 times
#Plot maximum confidence
pylab.figure()
for numPeers in sorted(peers.keys()):
percentUni, maxes = peers[numPeers]
labels = list(set([i[1] for i in sorted(maxes,
key=itemgetter(1))]))
percentUni = [i[0] for i in sorted(maxes, key=itemgetter(1))]
x = []
y = []
ci = []
for l in xrange(len(labels)):
x.append(l+1)
y.append(max(maxes[l*3:l*3+3]))
pylab.plot(x, y, marker='o', label = "N=%d"%numPeers)
pylab.title('Maximal confidence in sender')
pylab.xlabel('Contribute Interval')
pylab.ylabel('Percent confident')
pylab.ylim([0,1])
pylab.xlim([0.5, 7.5])
pylab.xticks(xrange(1,8), labels)
pylab.legend(loc='upper right')
The plot looks like this, with each legend entry having exactly 2 copies.
I know the loop only runs 3x, because if I put in a print statement to debug, it only prints the string 3x.
I did see this in my search, but didn't find it helpful:
Duplicate items in legend in matplotlib?
I had a similar problem. What I ended up doing is add plt.close() at the beginning of my loop. I suspect you're seeing 6 because you have a nested loop where you're changing the x and y.
It ended up being a bug/type on my part, where I was supposed to write
maxes = [i[0] for i in sorted(maxes, key=itemgetter(1))]
instead of
percentUni = [i[0] for i in sorted(maxes, key=itemgetter(1))]
This mistake meant that maxes remained a list of 2-tuples instead of a list of integers, which is why things were plotted twice. And because I restricted the y-axis, I never saw that there were additional data elements plotted.
Thanks for your help, those who did answer!

Categories