plot data in connected horizantla lines on python - python

I have these array data x and i want to plot horizantal line for each value in it in a specific sub-interval of the range y
please can any one help me ?
x=[2,4,3,5]
;y=np.linspace(0,20,20)

Can be done with a bit of logic and preparing the x and y coordinates-
import matplotlib.pyplot as plt
y = [2, 4, 3, 5]
ys = []
xs = []
step_length = [5, 4, 2, 3]
for i, ycoord in enumerate(y):
ys.extend([ycoord]*(step_length[i]))
xs.extend(list(range(len(xs) - i, len(xs) + step_length[i] - i)))
plt.plot(xs, ys)
plt.show()

Related

Python while loop replaces variable

if it runs, the figures should print out one by one. k = [3, 4, 5, 6, 2.1, 3.8, 5.5, 7.2]
[![enter image description here][1]][1]
but mine figures overwrites each other. so there has to be break or something?
[![enter image description here][2]][2]
from matplotlib import pyplot as plt
import numpy as np
def funcx(t, k, r):
x_1= r(k-1)np.cos(t)
x_2= r(np.cos((k-1)t))
x = x_1 + x_2
return x
def funcy(t, k, r):
y_1= r(k-1)np.sin(t)
y_2= rnp.sin((k-1)t)
y = y_1 - y_2
return y
def plot_function(k, r, string_plot):
plt.figure()
plt.plot(x_list, y_list, string_plot)
ax = plt.subplot()
ax.axis('off')
plt.show()
k = [3, 4, 5, 6, 2.1, 3.8, 5.5, 7.2]
r = 5
x_list =[]
y_list=[]
for i in range(0, len(k)):
for t in np.arange(0, 20*np.pi, 0.001):
x_list.append(funcx(t, k[i], r))
y_list.append(funcy(t, k[i], r))
plot_function(x_list, y_list, "b")
[![enter image description here][3]][3]
[1]: https://i.stack.imgur.com/qF3wR.png
[2]: https://i.stack.imgur.com/t5rS3.png
[3]: https://i.stack.imgur.com/lmyLL.png
this is how it should be: https://en.wikipedia.org/wiki/Hypocycloid
Do this changes to your code. Not sure if it is what you need.
import numpy as np
def funcx(t, k, r):
x_1= r*(k-1)*np.cos(t)
x_2= r*(np.cos((k-1)*t))
x = x_1 + x_2
return x
def funcy(t, k, r):
y_1= r*(k-1)*np.sin(t)
y_2= r*np.sin((k-1)*t)
y = y_1 - y_2
return y
def plot_function(xlist, ylist,k,ax):
ax[i].plot(x_list, y_list)
ax[i].set_title(f'k = {k}')
ax[i].axis('off')
#plt.plot(x_list, y_list, string_plot)
#ax = plt.subplot()
#plt.axis('off')
k = [3, 4, 5, 6, 2.1, 3.8, 5.5, 7.2]
r = 5
x_list =[]
y_list=[]
#Initialize the subplots before the for loop to avoid the overwriting.
fig, ax = plt.subplots(1,len(k),**{'figsize':(20,4)})
for i in range(0, len(k)):
for t in np.arange(0, 20*np.pi, 0.001):
x_list.append(funcx(t, k[i], r))
y_list.append(funcy(t, k[i], r))
plot_function(x_list, y_list,k[i],ax)

Plot a triangle contour/surface matplotlib python: tricontourf/meshgrid

Given the following image, where plt.Polygon was used to create the triangle and plt.contourf the contour, i would like to 'cut' off the regions marked in X so that i only get the contour inside the triangle. How would i do this?
I've tried placing NaN values in the mentioned regions but the edges are square and therefore requires a large meshgrid to generate a 'clean' cut between the unwanted and wanted regions. Rather is it more appropiate to use plt.tricontourf? If so how should one approach it?
Thanks #Zephyr for the tricontourf solution, Heres how i solved it without the use of tricontourf and simply a meshgrid
# =============== Define Points =============== #
left_point = np.array([8, 1])
top_point = np.array([10.75, 3.75])
right_point = np.array([13.5, 1])
# =============== Define Left Line Eq: y = mx+c =============== #
left_m = (top_point[-1] - left_point[-1]) / (top_point[0] - left_point[0])
left_c = left_point[-1] - left_m*left_point[0]
# =============== Define Right Line Eq: y = mx+c =============== #
right_m = (right_point[-1] - top_point[-1]) / (right_point[0] - top_point[0])
right_c = right_point[-1] - right_m*right_point[0]
# =============== Generate Spaced Points on Both Lines =============== #
n_points = 100
# x-coordinates on left line
X_left = np.linspace(left_point[0], top_point[0], n_points)
# y-coordinates on left line
Y_left = left_m * X_left + left_c
# x-coordinates on right line
X_right = np.linspace(right_point[0], top_point[0], n_points)
# y-coordinates on right line
Y_right = right_m * X_right + right_c
# Concatenate Left line X and Right line X: [X_left, X_right]
LR_X = np.hstack([X_left[:, None], X_right[:, None]])
# =============== Generate Spaced Points IN BETWEEN points on both lines =============== #
"""
# We can use lists to generate points between each adjacent points on the left/right line
# Then turn them into arrays
# NOTE: Y_left and Y_right are essentially equal so we could just use one of them
# XX = []
# YY = []
# for ii in range(n_points):
# XX.append(np.linspace(LR_X[ii, 0], LR_X[ii, 1], n_points).reshape(1, -1))
# YY.append(Y_left[ii]*np.ones(n_points).reshape(1, -1))
# XX = np.vstack(XX)
# YY = np.vstack(YY)
"""
# Or We could do this (Same thing)
XX = np.meshgrid(np.linspace(LR_X[:, 0], LR_X[:, 1], n_points))[0].reshape(n_points, n_points).T
YY = np.meshgrid([Y_left*np.ones(n_points)]*n_points)[0].reshape(n_points, n_points).T
# Im using a model to predict each point, so i had to flatten it out first
# i.e. XX.shape = (100, 100); YY.shape = (100, 100), WW.shape = (100*100, 2)
WW = np.c_[XX.ravel(), YY.ravel()]
ZZ = model.predict(WW).reshape(XX.shape)
# =============== Contour/Surface Plots =============== #
# Contour plot
fig1 = plt.figure(1, figsize=(8, 6))
ax1 = fig1.add_subplot(111)
levels = np.arange(Y.min(), Y.max())
contour_map = ax1.contourf(XX, YY, ZZ, cmap='viridis')
contour = ax1.contour(XX, YY, ZZ)
cbar = fig1.colorbar(contour_map, )
# Surface Plot
fig2 = plt.figure(2, figsize=(10, 6))
ax2 = fig2.add_subplot(projection='3d')
ax2.plot_surface(XX, YY, ZZ, cmap='viridis')
You could do it with matplotlib.pyplot.tricontourf, but it depends on the way you stored data.
You should have 4 arrays:
x array (1, N) with x coordinates
y array (1, N) with y coordinates
z array (1, N) with z values
triangles list of the index of x and y points which are the vertices of the clipping triangle
x = np.asarray([8, 10, 8, 14, 9, 11, 13, 10, 12, 11])
y = np.asarray([2, 2, 2, 2, 2.56666667, 2.56666667, 2.56666667, 3.13333333, 3.13333333, 3.7])
z = np.cos(2.5*x*x)*np.cos(1.5*y*x)
triangles = [[0, 3, 9]]
Then you can perform triangulation with:
triang = mtri.Triangulation(x, y, triangles)
Complete Code
import matplotlib.pyplot as plt
import matplotlib.tri as mtri
import numpy as np
x = np.asarray([8, 10, 8, 14, 9, 11, 13, 10, 12, 11])
y = np.asarray([2, 2, 2, 2, 2.56666667, 2.56666667, 2.56666667, 3.13333333, 3.13333333, 3.7])
z = np.cos(2.5*x*x)*np.cos(1.5*y*x)
triangles = [[0, 3, 9]]
triang = mtri.Triangulation(x, y, triangles)
fig, ax = plt.subplots()
t = ax.tricontourf(triang, z)
plt.colorbar(t)
plt.show()
If your data are not in this shape, you should re-shaping your array in order to get x, y and z as above described and calculate the triangles indeces list. Please, provide your data if you need help.

How to plot a scatter plot which would also represent the histogram for y value for each value for x

I have a set of X and Y data points (about 20k) that I would like to represent using a scatter plot.
The data set looks something list this
x = [1, 1, 2, 1, 2, 1, 1, 2]
y = [3.1, 3.1, 3.1, 1, 2, 3.1, 1, 2]
(not all values are integers in the data actual data set)
I would like to make a scatter plot with color of where the color would indicate the frequency of a particular value in 'y' for a particular 'x'
For this I tried to calculate the histogram of y for each x value but I always end up with a plot which is wrong. the codes I use are shown below
x = [1, 1, 2, 1, 2, 1, 1, 2]
y = [3.1, 3.1, 3.1, 1, 2, 3.1, 1, 2]
I = []
Y = []
C = []
for i in range (0, len(x)):
if x[i] not in I :
I.append(x[i])
for j in range (0, len(x)):
if x[i] == x[j]:
Y.append(y[j])
u,c = np.unique(Y, return_counts=True)
C.append(c)
Y = []
plt.scatter(x, y, s=70, c=C, cmap='RdYlBu', marker='o', edgecolors='black', linewidth=1, alpha=7)
plt.xlabel('x')
plt.ylabel('y')
plt.colorbar()
the final plot looks like this
final plot
It will be really helpful if someone could tell me where I'm making a mistake or how could I possibly achieve this. I'm very new to python so more explanation is appreciated.
Thank you in advance.
(also will it be possible to make the dot having the same value appear repeatedly with the same color?)
Here is a code that works for you :
import numpy as np
import matplotlib.pyplot as plt
x = np.array([1, 1, 2, 1, 2, 1, 1, 2])
y = np.array([3.1, 3.1, 3.1, 1, 2, 3.1, 1, 2])
X=[]
Y=[]
C=[]
for i in np.unique(x):
new_y = y[np.where(x==i)]
unique,count = np.unique(new_y, return_counts=True)
for j in range(len(unique)):
X.append(i)
Y.append(unique[j])
C.append(count[j])
plt.scatter(X,Y,c=C)
plt.colorbar()
What I do is that for each "unique" value of x I check the values of y using the build in numpy function where. Then my count is not much different from yours.
Here is the result:

How to plot a 3D scatter graph with a specified color for everypoint

This question might be stupid but I can't find the answer. I'm using python and I want to plot a scatter graph where x is of size Nx, y of size Ny, z of size Nz and where for every point (x[i] , y[j], z[k]) I have an intensity I[i,j,k] which is a real number.
I would like to plot this scatter graph where every point of coordinates (x,y,z) has a color depending on the intensity
An easy way could be to use pyplot.cm.get_cmap(). Example below is for 2D, I let you figure out the rest.
from matplotlib import pyplot as plt
X = [1, 2, 3, 4]
Y = [1, 2, 2, 3]
# list-like of the intensities for each point
I = [2, 5, 7, 7]
# Create the colors
colors = plt.cm.get_cmap(None, len(list(set(I))))
colors_dict = dict()
count = 0
for elt in I:
if elt not in colors_dict.keys():
colors_dict[elt] = colors(count)
count += 1
else:
continue
f, ax = plt.subplots(1, 1)
for k, x in enumerate(X):
y = Y[k]
i = I[k]
dot_color = colors_dict[i]
ax.scatter(x, y, s = 15, color = dot_color)
It is likely that better ways than the one above exist.

Two point segment plot in matplotlib

How can I plot a two point line segment plot as shown in the following figure
The data is like below
x = [1,2,3,4,5,6]
y = [1.2,1.2,-2.1, -2.1, 4.1, -4.1] #these y values are always in pair such that I need a solid line to connect these equivalent values and then a dotted line between this pair and the next pair.
Does this achieve what you were hoping?
import numpy as np
import matplotlib.pyplot as plt
x = [1, 2, 3, 4, 5, 6]
y = [1.2, 1.2, 2.1, 2.1, -4.1, -4.1]
plt.plot(x, y, 'm--')
pair_x_array = np.reshape(x, (-1, 2))
pair_y_array = np.reshape(y, (-1, 2))
for i, pair_x in enumerate(pair_x_array):
pair_y = pair_y_array[i]
plt.plot(pair_x, pair_y, 'm', linewidth=3)
plt.show()
Do you mean something like this?
import pylab
xdata = [0, 1, 2, 3, 4, 5]
ydata = [0, 1, 2, 2, 1, 0]
# Assuming xdata, ydata are of suitable length and type
plots = [pylab.plot(xdata[i:i + 2], ydata[i:i + 2], **whatever_keyword_arguments) for i in xrange(0, len(xdata), 2)]
pylab.show()
Edit after OP edit:
I see what you mean, and it's trivial to add the lines in dashes.
def plot_broken(xseq, yseq, even=True, **plot_kwargs):
size = len(xseq)
assert size == len(yseq)
assert size % 2 == 0
start = 0 if even else 1
return [pylab.plot(xseq[i:i + 2], yseq[i:i + 2], **plot_kwargs)
for i in xrange(start, size, 2)]
plots = plot_broken(xdata, ydata, even=True, color="m",
linestyle="solid")
plots += plot_broken(xdata, ydata, even=False, color="m",
linestyle="dashed")

Categories