I am new to matplotlib and I was playing with this library to plot data from a csv file. Without using the animation function the graph looks correct, but When I tried to use the animation, the graph connected the first and the last point. I looked stuff up, but I can't figure out how to solve this. Does anyone know how to solve this issue? Below is my code. Thanks in advance!
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import csv
x = []
y = []
fig = plt.figure()
ax1 = fig.add_subplot(1,1,1)
def animate(i):
with open("example.txt", "r") as csvfile:
plots = csv.reader(csvfile, delimiter=',')
for row in plots:
x.append(int(row[0]))
y.append(int(row[1]))
ax1.clear()
ax1.plot(x,y)
ani = animation.FuncAnimation(fig, animate, interval=1000)
plt.show()
You append all the same points over and over again to the lists to plot. So say the csv file contains numbers 1,2,3 what you are doing is reading them in, appending them to the list, plotting them, then reading them in again and appending them etc.
So x contains in
Step 1 : 1,2,3
Step 2 : 1,2,3,1,2,3
Step 3 : 1,2,3,1,2,3,1,2,3
Hence from step 2 on there will be a connection between 3 and 1.
I don't know what the purpose of this animation is since animating all the same points is quite useless. So there is no straight forward solution, apart from not animating at all.
Related
I'm new to python and have a question. I have a file.csv file that contains two columns.
FILE.csv
0.0000 9.0655
0.0048 9.0640
0.0096 9.0592
0.0144 9.0510
0.0192 9.0392
0.0240 9.0233
0.0288 9.0028
0.0336 8.9770
0.0384 8.9451
0.0432 8.9063
0.0480 8.8595
0.0528 8.8039
0.0576 8.7385
0.0624 8.6626
0.0000 11.0013
0.0048 11.0018
0.0096 11.0032
0.0144 11.0057
0.0192 11.0091
0.0240 11.0134
0.0288 11.0186
0.0336 11.0247
0.0384 11.0317
0.0432 11.0394
0.0480 11.0478
0.0528 11.0569
0.0576 11.0666
0.0624 11.0767
0.0672 11.0873
I tried to plot the graph from FILE.csv
with xmgrace and Gnuplot, and the result is very convincing.
I have two lines in the graph, as shown in the two figure below:
enter image description here
enter image description here
On the other hand, if I use my python script, the two lines are joined
here is my script:
import matplotlib.pyplot as plt
import pylab as plt
#
with open('bb.gnu') as f:
f=[x.strip() for x in f if x.strip()]
data=[tuple(map(float,x.split())) for x in f[2:]]
BX1=[x[0] for x in data]
BY1=[x[1] for x in data]
plt.figure(figsize=(8,6))
ax = plt.subplot(111)
plt.plot(BX1, BY1, 'k-', linewidth=2 ,label='Dos')
plt.plot()
plt.savefig("Fig.png", dpi=100)
plt.show()
And here's the result
enter image description here
My question, does it exist a solution to plot graph with Python, without generating the junction between the two lines.
In order to find a similar result to Gnuplot and xmgrace.
Thank you in advance for your help.
To my knowledge, matplotlib is only joining your two curves because you provide them as one set of data. This means that you need to call plot twice in order to generate two curves. I put your data in a file called data.csv and wrote the following piece of code:
import numpy
import matplotlib.pyplot as plt
data = numpy.genfromtxt('data.csv')
starts = numpy.asarray(data[:, 0] == 0).nonzero()[0]
fig, ax = plt.subplots(nrows=1, ncols=1, num=0, figsize=(16, 8))
for i in range(starts.shape[0]):
if i == starts.shape[0] - 1:
ax.plot(data[starts[i]:, 0], data[starts[i]:, 1])
else:
ax.plot(data[starts[i]:starts[i + 1], 0],
data[starts[i]:starts[i + 1], 1])
plt.show()
which generates this figure
What I do with starts is that I look for the rows in the first column of data which contain the value 0, which I consider to be the start of a new curve. The loop then generates a curve at each iteration. The if statement discerns between the last curve and the other ones. There is probably more elegant, but it works.
Also, do not import pylab, it is discouraged because of the unnecessary filling of the namespace.
How to get many figures without closing first one in matplotlib one by one.
My code is as follows:
import matplotlib.pyplot as plt
x = [1,2,3,4,5,6,7,8,9,10]
y = [1,4,9,16,25,36,49,64,81,100]
z=[1,3,4,5,19,13,17,12,15,10]
v=[1,2,4,5,7,8,90,3,2,2]
def func(x,y):
plt.plot(x, y)# I want the first graph to stay and get second one without closing first
plt.show()
return
func(x,y)
myinput=int(input())
if myinput==1:
func(x,z)
else:
func(x,v)
#something like this i want
#answering myself after spending lot of time
x = [1,2,3,4,5,6,7,8,9,10]
y = [1,4,9,16,25,36,49,64,81,100]
z=[1,3,4,5,19,13,17,12,15,10]
v=[1,2,4,5,7,8,90,3,2,2]
def func(x,y,index):
fig=plt.figure(index)
fig1=fig.add_subplot(1,1,1)
fig1.plot(x, y)
plt.show(block=False)
return
my_input=1
while(my_input!=-1):
my_input=int(input())
func(x,y,my_input)
As a shortened version of #noman's answer:
plt.show(block=False)
For example, I used it like this to generate two plots from one script, without needing to close the first plot:
# first plot
fig = plt.figure()
plt.scatter(.....whatever....)
plt.show(block=False)
# second plot
fig = plt.figure()
plt.line(.....whatever....)
plt.show()
I would like to plot select data from a dictionary of the following format:
dictdata = {key_A: [(1,2),(1,3)]; key_B: [(3,2),(2,3)]; key_C: [(4,2),(1,4)]}
I am using the following function to extract data corresponding to a specific key and then separate the x and y values into two lists which can be plotted.
def plot_dictdata(ax1, key):
data = list()
data.append(dictdata[key])
for list_of_points in data:
for point in list_of_points:
x = point[0]
y = point[1]
ax1.scatter(x,y)
I'd like to be able to call this function multiple times (see code below) and have all relevant sets of data appear on the same graph. However, the final plot only shows the last set of data. How can I graph all sets of data on the same graph without clearing the previous set of data?
fig, ax1 = plt.subplots()
plot_dictdata(ax1, "key_A")
plot_dictdata(ax1, "key_B")
plot_dictdata(ax1, "key_C")
plt.show()
I have only just started using matplotlib, and wasn't able to figure out a solution using the following examples discussing related problems. Thank you in advance.
how to add a plot on top of another plot in matplotlib?
How to draw multiple line graph by using matplotlib in Python
Plotting a continuous stream of data with MatPlotLib
It could be that the problem is at a different point than you think it to be. The reason you only get the last point plotted is that in each loop step x and y are getting reassigned, such that at the end of the loop, each of them contain a single value.
As a solution you might want to use a list to append the values to, like
import matplotlib.pyplot as plt
dictdata = {"key_A": [(1,2),(1,3)], "key_B": [(3,2),(2,3)], "key_C": [(4,2),(1,4)]}
def plot_dictdata(ax1, key):
data = list()
data.append(dictdata[key])
x=[];y=[]
for list_of_points in data:
for point in list_of_points:
x.append(point[0])
y.append(point[1])
ax1.scatter(x,y)
fig, ax1 = plt.subplots()
plot_dictdata(ax1, "key_A")
plot_dictdata(ax1, "key_B")
plot_dictdata(ax1, "key_C")
plt.show()
resulting in
It would be worth noting that the plot_dictdata function could be simplified a lot, giving the same result as the above:
def plot_dictdata(ax1, key):
x,y = zip(*dictdata[key])
ax1.scatter(x,y)
I have two data sets, Points and Pointsize. I want to animate the plot with the change of coordinate(Points) and size(Pointsize) of points. But I only can update Points. The code below is showing that three points move with change of data of Points. What I want is, the points not only move, but also change their sizes.I tried to use scat.set_offsets(Points['xy'],Pointsize) to achieve my goal. But the error shows "TypeError: set_offsets() takes exactly 2 arguments (3 given)". I also tried to use duplicate set_offsets to update both Points['xy'] and Pointsize separately. The error shows "ValueError: total size of new array must be unchanged".
I have no idea how to solve that problem. Someone can tell me a way or solution to achieve my goal? I will appreciate your help. Thank you very much.
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
def updata(frame_number):
current_index = frame_number % 3
a = [[10,20,30],[40,50,60],[70,80,90]]
Points['xy'][:,0] = np.asarray(a[current_index])
Points['xy'][:,1] = np.asarray(a[current_index])
Pointsize = a[current_index]
scat.set_offsets(Points['xy'])
#scat.set_offsets(Pointsize)
#scat.set_offsets(Points['xy'],Pointsize)
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_title("For Dataset %d" % current_index)
fig = plt.figure(figsize=(5,5))
ax = fig.add_subplot(111)
Points = np.zeros(3,dtype=[('xy',float,2)])
Pointsize = [10] * 3
scat = ax.scatter(Points['xy'][:,0],Points['xy'][:,1],s=Pointsize,alpha=0.3,edgecolors='none')
ax.set_xlim(0,100)
ax.set_ylim(0,100)
animation = FuncAnimation(fig,updata,frames=50,interval=600)
plt.show()
As seen in the official matplotlib example, you would use
scat.set_sizes(Pointsize)
to update the size of scatter points.
I am writing a program which generates satisfiable models (connected graphs) for a specific input string. The details here are not important but the main problem is that each node has a label and such label can be lengthy one. So, what happens is that it does not fit into the figure which results in displaying all the nodes but some labels are partly displayed... Also, the figure that is displayed does not provide an option to zoom out so it is impossible to capture entire graph with full labels on one figure.
Can someone help me out and perhaps suggest a solution?
for i in range(0,len(Graphs)):
graph = Graphs[i]
custom_labels={}
node_colours=['y']
for node in graph.nodes():
custom_labels[node] = graph.node[node]
node_colours.append('c')
#nx.circular_layout(Graphs[i])
nx.draw(Graphs[i], nx.circular_layout(Graphs[i]), node_size=1500, with_labels=True, labels = custom_labels, node_color=node_colours)
#show with custom labels
fig_name = "graph" + str(i) + ".png"
#plt.savefig(fig_name)
plt.show()
Update picture added:
You could scale the figure
import networkx as nx
import matplotlib.pyplot as plt
G = nx.Graph()
G.add_edge('a'*50,'b'*50)
nx.draw(G,with_labels=True)
plt.savefig('before.png')
l,r = plt.xlim()
print(l,r)
plt.xlim(l-2,r+2)
plt.savefig('after.png')
before
after
You could reduce the font size, using the font_size parameter:
nx.draw(Graphs[i], nx.circular_layout(Graphs[i]), ... , font_size=6)