I'm currently having a small problem with plotting several different lines in a 3d plot. I have a list of lists containing three numpy arrays corresponding to the xyz coordinates for the three points on each line, i.e.
lines=[[array([10,0,0]),array([10,0,101.5]),array([-5,0,250])],[array([9,0,0]), array([9,0,101.5]),array([-4,0,250])]]
would represent 2 lines with 3 sets of xyz coordinates in each (the first one here would be (10,0,0),(10,0,101.5) and (-5,0,250)).
In general I would have n lines in this list each with 3 sets of xyz coordinates each. I would like to plot these lines on a single 3d plot with matplotlib. All I've managed to do so far is to create n plots each containing a single line.
Thanks for the help!
EDIT:
I have a list 'lines' containing 'line' objects which are just lists themselves containing 3 numpy arrays for the 3 points on each line. I tried to use the following method:
for line in lines:
fig = plt.figure()
ax = fig.gca(projection='3d')
z = []
for i in [0,1,2]:
z.append(line[i][2])
x = []
for i in [0,1,2]:
x.append(line[i][0])
y = []
for i in [0,1,2]:
y.append(line[i][1])
ax.plot(x, y, z, label='path')
plt.show()
I think I understand why this gives me 2 plots of lines 1 and 2 but I can't figure out a way to put both lines on the same plot.
You almost got it. The solution to your problem is simple, just move required statments out of for loop:
import matplotlib.pyplot as plt
lines=[[array([10,0,0]),array([10,0,101.5]),array([-5,0,250])],[array([9,0,0]), array([9,0,101.5]),array([-4,0,250])]]
fig = plt.figure()
ax = fig.gca(projection='3d')
for line in lines:
z = []
for i in [0,1,2]:
z.append(line[i][2])
x = []
for i in [0,1,2]:
x.append(line[i][0])
y = []
for i in [0,1,2]:
y.append(line[i][1])
ax.plot(x, y, z, label='path')
plt.show()
I had a similar problem trying to plot a 3D path between locations, and this was about the closest / most helpful solution I found. So just if anybody else is trying to do this and might find this similar solution sheds a bit of light :
for location in list_of_locations:
x_list.append(locdata[location].x) # locdata is a dictionary with the co-ordinates of each named location
y_list.append(locdata[location].y)
z_list.append(locdata[location].z)
fig = plt.figure()
ax = fig.gca(projection='3d')
for i in range(len(x_list)-1):
xs = [x_list[i], x_list[i+1]]
ys = [y_list[i], y_list[i+1]]
zs = [z_list[i], z_list[i+1]]
ax.plot(xs,ys,zs)
plt.show()
I'm sure it doesn't need to be two separate for loops but for my little data set this was totally fine, and easy to read.
Related
My code loads 15 time-series data via a for loop. The time-series are then transformed into 3D phase space. I would like to plot the 15 trajectories into one 3D coordinate system (phase space), but my code creates a new 3D plot for every time-series (Data).
Here is the relevant part of my code:
for Subject in Subjects:
Data = np.loadtxt("path/to/files...")
Colormap = plt.get_cmap("tab20c_r")
Segment_Colormap = Colormap(np.linspace(0, 1, len(Subjects)))
x_list = pd.Series(Data) # pd.Series
y_list = x_list.shift(Mean_Lag) # pd.DataFrame.shift
z_list = x_list.shift(Mean_Lag*2)
plt.figure().add_subplot(projection="3d")
plt.plot(x_list, y_list, z_list, lw=0.5,
c=Segment_Colormap[Subjects.index(Subject)])
plt.show()
I know that the issue is due to the fact that the line plt.figure().add_subplot(projection="3d") is part of my for loop.
However, when I remove the related code lines out of the loop, such as follows
x_list = pd.Series(Data) # pd.Series
y_list = x_list.shift(Mean_Lag) # pd.DataFrame.shift
z_list = x_list.shift(Mean_Lag*2)
plt.figure().add_subplot(projection="3d")
plt.plot(x_list, y_list, z_list, lw=0.5,
c=Segment_Colormap[Subjects.index(Subject)])
plt.show()
the result is that my code only plots the last time-series (Data) of the for loop. What would be the solution so that all 15 loaded files by the for loop are plotted into one and the same 3D plot? I didn't face this problem with 2D plots before, so something seems to be different for a 3D plot.
In your first case, the issue is that you call plt.figure().add_subplot(projection="3d") inside the for loop, meaning a new figure is created with each iteration.
In your second case, the issue is that you call plt.plot(x_list, y_list, z_list, lw=0.5, c=Segment_Colormap[Subjects.index(Subject)]) outside of the for loop, meaning only the last iteration is plotted (i.e. the last values of x_list, y_list and z_list are used).
To fix this, you want a combination of the two cases. You want to declare the figure outside of the for loop and then call plot inside of the for loop.
For example (using simple data and two for loop iterations):
x = [1, 2, 3, 4]
y = z = x
my_list = [x, [2*X for X in x]] # list of lists to be looped over
plt.figure().add_subplot(projection="3d")
for l in my_list:
plt.plot(l, y, z)
Output:
I'm trying to to a 3D scatter plot (or any 3D plot that will work) in Python 3.7.6. I have x, y, and z data in the following formats:
x = [[1,2,3,46,2,...],[6,4,24,56,4,...],...[7,3,52,524,3...]]
y = [[3,4,5,63,...],[23,35,64,4,6,3...],...[34,345,45,4,3,4,...]]
z = [1,2,3,4,5,6,7,8,...]
The data corresponds to essentially a 3D volume where x[0] and y[0] are plotted at z[0], and so on. The data that I put there is example data, not actual numbers that I am using.
When I try to plot using
ax.scatter(x,y,z)
I get the error as seen in the attached figure .
My code is written as :
fig = plt.figure()
ax = plt.axes(projection='3d')
ax.scatter(xphases,yphases,zphases)
I have 5 graphs. My code continue with this way:
plots = zip(x,y)
def loop_plot(plots):
figs = {}
axs = {}
for idx, plot in enumerate(plots):
figs[idx] = plt.figure()
axs[idx] = figs[idx].add_subplot(111)
axs[idx].plot(plot[0],plot[1])
return figs, axs
figs,axs=loop_plot(plots)
This code create 5 different graph. BUt I would like to plot 5 graph in one figure. I mean, I would like to create 5 different figure into one code. How can I manage it? I have 5 different x and y dataset. how can I write subplot code with for loop?
You have to be careful about using the terms figure and axes when talking about matplotlib, as they mean slightly different things to normal English usage. An axes object is a pair of (x,y) axes, and a figure is a container that holds one or more axes. The reason I say that is because the code to solve your problem will be different if you want five different lines on one set of axes, or if you want one figure containing 5 separate axis, each with one line.
5 separate axes
def loop_plot1(plots):
shape = (2, 3) # Fix this to make it more general if you want to handle more than 6 plots!
list_ax = []
fig = plt.figure()
for i, plot in enumerate(plots):
idx = i + 1
list_ax.append(fig.add_subplot(shape[0], shape[1], idx)) # a more general way of writing, eg, add_subplot(231) etc.
list_ax[i].plot(plot[0], plot[1])
loop_plot1(plots)
5 lines on one axes
def loop_plot2(plots):
shape = (2, 3) # Fix this to make it more general if you want to handle more than 6 plots!
fig, ax = plt.subplots() # implicitly does fig = plot.figure() // fig.add_subplot(111)
for i, plot in enumerate(plots):
ax.plot(plot[0], plot[1])
loop_plot2(plots)
I have 1 y variable and hundreds of X variables that I want to create scatter plots through a for loop. I have codes that allow me to generate the plots but I need x, y labels to be marked accordingly as well. how can I do this? Any help is appreciated.
here are the codes:
figures = []
for column in X_uni:
f = plt.figure(figsize=(6,6))
figures += [f] # This appends a figure f to the list of figures
ax = plt.axes()
ax.plot(X_uni[column], y_data, marker = 'o', ls='', ms = 3.0)
Use
ax.set_xlabel(column)
in your for loop. And add a ylabel:
ax.set_ylabel("ylabel")
I would like to plot multiple lines in a 3D plot in Python. My input consists of two n x 3 arrays, say pos1 and pos2, corresponding to two lists of 3D points (row = x,y,z coordinates). I need to plot a line connecting the ith point in pos1 to the ith point in pos2, for each i.
I have working code, but I am certain that it is terrible and that there is a much better way to implement this.
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
# get plot set up
fig = plt.figure()
ax = fig.add_subplot(111, projection = '3d')
# minimal working example: two pairs.
pos1 = np.array([[0,0,0],[2,2,2]])
pos2 = np.array([[1,1,1],[3,3,3]])
xvals = np.transpose(np.array([pos1[:,0], pos2[:,0]]))
yvals = np.transpose(np.array([pos1[:,1], pos2[:,1]]))
zvals = np.transpose(([pos1[:,2], pos2[:,2]]))
N = len(pos1)
# call plot on each line
for i in range(N):
ax.plot(xvals[i],yvals[i],zvals[i])
plt.show()
Specifically, I do not think it is necessary to define the three intermediate arrays xvals, yvals, zvals. Is there a cleaner alternative to this? Should I be passing a list to plot, for example?
I've never done 3D plotting before, so I can't say whether this would be the best method using the tools matplotlib has to offer. But you could make good use of the zip function.
pos1 = np.array([[0,0,0],[2,2,2]])
pos2 = np.array([[1,1,1],[3,3,3]])
for point_pairs in zip(pos1, pos2):
xs, ys, zs = zip(*point_pairs)
ax.plot(xs, ys, zs)