Edit the plot to make it smooth - python
I seek help in editing my plot. Here in the image you can see I am getting vertical lines in all the six plots.
But I want a smooth curve.
Here is my code what I have tried so far
import pandas as pd
from matplotlib import pyplot as plt
import numpy as np
from math import *
from scipy.stats import skew
from scipy.interpolate import make_interp_spline
import scipy
import seaborn as sns
plt.rcParams["figure.figsize"] = (12,3)
df=pd.read_csv("plot_data00.txt")
df=df[df['DOY'].between(184,187)]
df["HR"] = df["HR"]/24
df["DOY"] = df["DOY"]+ df["HR"]
df.to_csv("final_plot_data.txt")
#define variables to plot
import matplotlib.pyplot as plt
fig,axes= plt.subplots(nrows=6, ncols=1, squeeze=False)
x = df["DOY"]
y = df["By"]
z = df["Bz"]
a = df["Vsw"]
b = df["Nsw"]
c = df["reconnection_rate"]
d = df["magnetopause_distance"]
#create a figure and edit size
fig=plt.figure(figsize=(20,17))
#define subplots and define their position
plt1=fig.add_subplot(611)
plt2=fig.add_subplot(612)
plt3=fig.add_subplot(613)
plt4=fig.add_subplot(614)
plt5=fig.add_subplot(615)
plt6=fig.add_subplot(616)
plt1.plot("DOY", "By", data=df)
plt1.set_ylabel("By",size=16)
plt1.set_title("3-6 July 2003",size=20)
plt1.get_yaxis().set_label_coords(-0.05,0.5)
plt2.plot("DOY", "Bz", data=df)
plt2.set_ylabel("Bz",size=16)
plt2.get_yaxis().set_label_coords(-0.05,0.5)
plt3.plot("DOY", "Vsw", data=df)
plt3.set_ylabel("Vsw",size=16)
plt3.get_yaxis().set_label_coords(-0.05,0.5)
plt4.plot("DOY", "Nsw", data=df)
plt4.set_ylabel("Nsw",size=16)
plt4.get_yaxis().set_label_coords(-0.05,0.5)
plt5.plot("DOY", "reconnection_rate", data=df)
plt5.set_ylabel("MRR",size=16)
plt5.get_yaxis().set_label_coords(-0.05,0.5)
plt6.plot("DOY", "magnetopause_distance", data=df)
plt6.set_ylabel("MD",size=16)
plt6.set_xlabel("Day of Year",size=16)
plt6.get_yaxis().set_label_coords(-0.05,0.5)
#plt.subplots_adjust(hspace = ,wspace = 5)
#saving plot in .jpg format
plt.savefig('myplot03.jpg', format='jpeg',dpi=None, edgecolor='g', transparent=True, bbox_inches='tight')
I could have add my data, but no option seems better to represent it, a it is large(Suggestions are invited).
Thankyou for your time.
UPDATE:
The sample data for use is:
,Unnamed: 0,Unnamed: 0.1,index,YYYY,DOY,HR,MN,By,Bz,Vsw,Nsw,reconnection_rate,magnetopause_distance
0,225369,225369,263522,2003,184.0,0.0,2,4990000000.0,670000000.0,0.5928000000000002,1.49e-06,12573.256929898798,10.858269653698725
1,225370,225370,263523,2003,184.0,0.0,3,4080000000.0,390000000.0000001,0.5825,1.47e-06,11009.972803627901,10.946523155327649
2,225371,225371,263524,2003,184.0,0.0,4,4300000000.000002,-110000000.0,0.5675,1.4499999999999999e-06,13184.030740514894,11.067370358771116
1420,226789,226789,265056,2003,185.04340277777774,0.0017361111111111108,36,1100000000.0,4550000000.0,0.6971,4.589999999999999e-06,6.417619779966155,8.528263110991979
1421,226790,226790,265057,2003,185.04340277777774,0.0017361111111111108,37,530000000.0,6020000000.0,0.7007000000000001,4.17e-06,0.09620386453014222,8.650894534287474
1422,226791,226791,265058,2003,185.04340277777774,0.0017361111111111108,38,-3110000000.0,6230000000.000001,0.6958000000000002,4.779999999999998e-06,187.4614444320996,8.476077939976314
2765,228134,228134,266471,2003,186.04340277777774,0.0017361111111111108,11,3510000000.0000005,-2500000000.0,0.7323999999999999,1.7399999999999999e-06,2791.603594666996,9.860980027267642
2766,228135,228135,266472,2003,186.04340277777774,0.0017361111111111108,12,2000000000.0,-4340000000.000002,0.7396,1.42e-06,102.51414877271608,10.167496717459473
4048,229417,229417,267898,2003,187.0,0.0,58,5280000000.000001,1240000000.0,0.6935,1.22e-06,12837.913793204994,10.654153236043083
4049,229418,229418,267899,2003,187.0,0.0,59,3470000000.0,3690000000.0,0.6901,1.24e-06,1136.6725720724482,10.642739751911767
Sorry it looks clumsy, but it will help you to understand what i want to do actually.
Use scipy.interpolate module:
Plot raw data
sr = df.set_index('DOY')['Bz']
x = sr.index.values
y = sr.values
tck, u = interpolate.splprep([x, y])
u = np.linspace(0, 1, num=100, endpoint=True)
out = interpolate.splev(u, tck)
plt.plot(x, y, 'b', out[0], out[1], 'r')
plt.show()
Plot using the mean for same DOY
sr = df.set_index('DOY')['Bz'].groupby('DOY').mean()
x = sr.index.values
y = sr.values
tck, u = interpolate.splprep([x, y])
u = np.linspace(0, 1, num=100, endpoint=True)
out = interpolate.splev(u, tck)
plt.plot(x, y, 'b', out[0], out[1], 'r')
plt.show()
Combined
sr = df.set_index('DOY')['Bz']
x = sr.index.values
y = sr.values
sr2 = sr.groupby(level=0).mean()
x2 = sr2.index.values
y2 = sr2.values
tck, u = interpolate.splprep([x2, y2])
u = np.linspace(0, 1, num=100, endpoint=True)
out = interpolate.splev(u, tck)
plt.plot(x, y, 'b', out[0], out[1], 'r')
plt.show()
Related
The Matplotlib Result is Different From WolfarmAlpha
I want to plot some equation in Matplotlib. But it has different result from Wolframalpha. This is the equation: y = 10yt + y^2t + 20 The plot result in wolframalpha is: But when I want to plot it in the matplotlib with these code # Creating vectors X and Y x = np.linspace(-2, 2, 100) # Assuming α is 10 y = ((10*y*x)+((y**2)*x)+20) # Create the plot fig = plt.figure(figsize = (10, 5)) plt.plot(x, y) The result is: Any suggestion to modify to code so it has similar plot result as wolframalpha? Thank you
As #Him has suggested in the comments, y = ((10*y*x)+((y**2)*x)+20) won't describe a relationship, so much as make an assignment, so the fact that y appears on both sides of the equation makes this difficult. It's not trivial to express y cleanly in terms of x, but it's relatively easy to express x in terms of y, and then graph that relationship, like so: import numpy as np import matplotlib.pyplot as plt y = np.linspace(-40, 40, 2000) x = (y-20)*(((10*y)+(y**2))**-1) fig, ax = plt.subplots() ax.plot(x, y, linestyle = 'None', marker = '.') ax.set_xlim(left = -4, right = 4) ax.grid() ax.set_xlabel('x') ax.set_ylabel('y') Which produces the following result: If you tried to plot this with a line instead of points, you'll get a big discontinuity as the asymptotic limbs try to join up So you'd have to define the same function and evaluate it in three different ranges and plot them all so you don't get any crossovers. import numpy as np import matplotlib.pyplot as plt y1 = np.linspace(-40, -10, 2000) y2 = np.linspace(-10, 0, 2000) y3 = np.linspace(0, 40, 2000) x = lambda y: (y-20)*(((10*y)+(y**2))**-1) y = np.hstack([y1, y2, y3]) fig, ax = plt.subplots() ax.plot(x(y), y, linestyle = '-', color = 'b') ax.set_xlim(left = -4, right = 4) ax.grid() ax.set_xlabel('x') ax.set_ylabel('y') Which produces this result, that you were after:
Plotting a line between 2-D point to its corresponding value in 3-D
I am trying to plot a dashed line in a 3-D Matplotlib plot. I would like to get a dashed line between each (x_pt, y_pt) to its corresponding z_pt. from mpl_toolkits import mplot3d import numpy as np import matplotlib.pyplot as plt from matplotlib import cm import matplotlib matplotlib.rcParams['mathtext.fontset'] = 'cm' matplotlib.rcParams['axes.labelsize'] = 13 def z_function(x, y): a = 1 b = 5.1/(4*np.pi**2) c = 5/np.pi r = 6 s = 10 t = 1/(8*np.pi) return a*(y - b*x**2 + c*x - r)**2 + s*(1 - t)*np.cos(x) + s x = np.linspace(-5, 10, 100) y = np.linspace(0, 15, 100) indexes = np.random.randint(0, 100, 5) x_pt = x[indexes] y_pt = y[indexes] z_pt = z_function(x_pt, y_pt) fig = plt.figure() ax = fig.gca(projection='3d') ax.scatter(x_pt, y_pt, color='k', marker='x', depthshade=False) ax.scatter(x_pt, y_pt, z_pt, color='k', marker='^', depthshade=False) ax.set_xticks([-5, 0, 5, 10]) ax.set_yticks([0, 5, 10, 15]) ax.set_zticks([100, 200, 300]) ax.view_init(30, -120) ax.set_xlabel(r'$x_1$') ax.set_ylabel(r'$x_2$') ax.zaxis.set_rotate_label(False) ax.set_zlabel(r'$f(x)$', rotation=0) ax.w_xaxis.pane.fill = False ax.w_yaxis.pane.fill = False ax.w_zaxis.pane.fill = False plt.show() Can anyone help me with this?
If I understand your problem correctly, you need to connect the point (x,y,0) to (x,y,z) like so: for x_,y_,z_ in zip(x_pt, y_pt, z_pt): ax.plot([x_,x_],[y_,y_],[0,z_], '--', c='grey')
It should be as simple as: ax.plot(x_pt, y_pt, zs=z_pt, color='blue', marker='--', depthshade=False) alternatively using: ax.plot3D(x_pt, y_pt, z_pt, marker='--') UPDATE: You will need to create extra dummy coordinates for each point on the x-y axis, like so: import numpy as np n = 10 # number of points in the line for i in len(x_pt): x_range = np.linspace(0, x_pt[i], n) y_range = np.linspace(0, y_pt[i], n) ax.plot3D(x_range, y_range, [z_pt[i]]*n, marker='--') NOTE: Untested
Difficulty plotting a two dimensional lognorm surface
here is the code im using and I've also attached the output. I'd like to plot a two dimensional lognorm function as a 3d surface, the above code is supposed to do this however the output results in the entire plane being skewed rather than just the z values. any help or suggestions would be greatly appreciated. dx = 90 - (-90) dy = 90 - (-90) c = [dx + dx/2.0, dy+dy/2.0] z = np.zeros((400, 400)) x = np.linspace(-90, 90, 400) y = x.copy() for i in range(len(x)): for j in range(len(y)): p =[x[i], y[j]] d = math.sqrt((p[0]-c[0])**2 + (p[1]-c[1])**2) t = d z[i][j] = lognorm.pdf(t, 1.2) fig = plt.figure() ax = fig.add_subplot(111, projection = '3d') ax.plot_surface(x,y, z, cmap = 'viridis') plt.show() output of the provided code ideally I'd like for it to look something like this. this is the image here
I think you wanted to plot a 3D surface and here is an example: #!/usr/bin/python3 # 2018/10/25 14:44 (+0800) # Plot a 3D surface from scipy.stats import norm, lognorm import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D xy = np.linspace(-5, 5, 400) xx, yy = np.meshgrid(xy) t = np.sqrt(xx**2 + yy**2) zz = lognorm.pdf(t, 1.2) fig = plt.figure() ax = fig.add_subplot(111, projection = '3d') ax.plot_surface(xx,yy, zz, cmap = 'viridis') plt.show()
Python Matplotlib - imshow but with hexagons
Code is: import numpy as np import matplotlib.pyplot as plt from matplotlib import colors example_data = np.random.randint(4, size=(40,44)) cmap = colors.ListedColormap(['black', 'green', 'red', 'blue']) bounds = [0,1,2,3,4] norm = colors.BoundaryNorm(bounds, cmap.N) img = plt.imshow(example_data, interpolation = 'nearest', origin = 'lower', cmap = cmap, norm = norm) Which gets me roughly what I want. What I am looking for is if there is a way to get the shape of each tile to be hexagonal rather than square? I think imshow might not be the way to do it but if there is a way you can change the default tile it would be good. Thanks.
Here is a solution using patches: import numpy as np import matplotlib.pyplot as plt from matplotlib import colors import matplotlib.patches as mpatches from matplotlib.collections import PatchCollection nx = 40 ny = 44 example_data = np.random.randint(4, size=(nx,ny)) cmap = colors.ListedColormap(['black', 'green', 'red', 'blue']) bounds = [0,1,2,3,4] norm = colors.BoundaryNorm(bounds, cmap.N) x = np.linspace(0, 1, nx) y = np.linspace(0, 1, ny) X, Y = np.meshgrid(x, y) dx = np.diff(x)[0] dy = np.diff(y)[0] ds = np.sqrt(dx**2 + dy**2) patches = [] for i in x: for n, j in enumerate(y): if n%2: polygon = mpatches.RegularPolygon([i-dx/2., j], 6, 0.6*dx) else: polygon = mpatches.RegularPolygon([i, j], 6, 0.6*dx) patches.append(polygon) collection = PatchCollection(patches, cmap=cmap, norm=norm, alpha=1.0) fig, ax = plt.subplots(1,1) ax.add_collection(collection) collection.set_array(example_data.ravel()) plt.show() which looks like this, Previous solution, it doesn't tessellate nicely and the hexagons are poorly shaped but you could use a scatter plot with coloured hexagons, import numpy as np import matplotlib.pyplot as plt from matplotlib import colors nx = 40 ny = 44 example_data = np.random.randint(4, size=(nx,ny)) cmap = colors.ListedColormap(['black', 'green', 'red', 'blue']) bounds = [0,1,2,3,4] norm = colors.BoundaryNorm(bounds, cmap.N) x = np.linspace(0, 1, nx) y = np.linspace(0, 1, ny) X, Y = np.meshgrid(x, y) img = plt.scatter(X.ravel(),Y.ravel(),c=example_data.ravel(), cmap=cmap, norm=norm, s=360, marker=(6, 0), alpha=0.4) plt.colorbar(img) plt.show() which looks like,
Interactively changing the alpha value of matplotlib plots
I've looked at the documentation, but I can't seem to figure out if this is possible - I have a dataset, with x and y values and discrete z values. Multiple pairs of (x,y) share the same z value. What I want to do is when I mouseover one point with a particular z value, the alpha of all the points with the same z values goes to 1 - i.e., If all the alpha values are initially 0.5, I'd like only the points with the same z value to go to 1. Here's a minimal working example to illustrate what I'm talking about : #! /usr/bin/env python import numpy as np import matplotlib.pyplot as plt x = np.random.randn(100) y = np.random.randn(100) z = np.arange(0, 10, 1) z = np.repeat(z, 10) im = plt.scatter(x, y, c=z, alpha = 0.5) plt.colorbar(im) plt.show()
You can probably fake what you want to achieve using a second plot: import numpy as np import matplotlib.pyplot as plt Z = np.zeros(1000, dtype = [("Z", int), ("P", float, 2)]) Z["P"] = np.random.uniform(0.0,1.0,(len(Z),2)) Z["Z"] = np.random.randint(0,50,len(Z)) def on_pick(event): z = Z[event.ind[0]]['Z'] P = Z[np.where(Z["Z"] == z)]["P"] selection_plot.set_data(P[:,0],P[:,1]) plt.draw() fig = plt.figure(figsize=(10,10), facecolor='white') fig.canvas.mpl_connect('pick_event', on_pick) ax = plt.subplot(111, aspect=1) ax.plot(Z['P'][:,0], Z['P'][:,1], 'o', color='k', alpha=0.1, picker=5) selection_plot, = ax.plot([],[], 'o', color='black', alpha=1.0, zorder=10) plt.show()