I have zero background in programming. I am trying to code something for my class and it is giving me an error "not enough values to unpack (expected 2, got 1)". What might be wrong with my codes?
from mpl_toolkits.basemap import Basemap
import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
import shapefile as shp
#Read x, y, z file
data = pd.read_excel('RegionV.xlsx', header = None)
# Get X, Y, Z values from file
data = np.array(data)
data = data.astype(np.float)
x = data[:,0]
y = data[:,1]
z = data[:,2]
#Mask negative values of z (bathemetry)
zz = np.ma.masked_where(z <= 0, z)
#Create a map using basemap
fig = plt.figure(figsize=(10,10))
map = Basemap(projection='mill',llcrnrlat=11,urcrnrlat=15,\
llcrnrlon=122,urcrnrlon=125,resolution='h')
lon = np.linspace(min(x), max(x))
lat = np.linspace(min(y), max(y))
xs, ys = np.meshgrid(lon, lat)
x, y = map(xs, ys)
map.drawparallels(np.arange(12.,14.,0.5), labels=[0,0,0,1])
map.drawmeridians(np.arange(123.,126.,0.5), labels=[1,0,0,0])
#Plot
cmap = plt.cm.jet
cmap.set_bad(color='white')
m.pcolormesh(x, y, zz, cmap=cmap, vmax=1300, vmin=0)
m.colorbar(location='right', label='meters')
map.drawmapboundary()
map.drawcoastlines()
the first part of the error message says:
ValueError Traceback (most recent call last)
<ipython-input-50-3d7531011dc2> in <module>
44 cmap = plt.cm.jet
45 cmap.set_bad(color='white')
---> 46 m.pcolormesh(xs, ys, zz, cmap=cmap, vmax=1300, vmin=0)
47 m.colorbar(location='right', label='meters')
then, at the end,
ValueError: not enough values to unpack (expected 2, got 1)
Stackoverflow is not allowing me to post the entire error message. Hope everyone who see my post understands what I mean.
I think that the problem is with line x, y = map(xs, ys). Look at this page for the documentation of the Basemap() function and the example usage (search for ".basemap" keyword). It says that the example usage is:
# create Basemap instance for Robinson projection.
m = Basemap(projection='robin',lon_0=0.5*(lons[0]+lons[-1]))
# compute map projection coordinates for lat/lon grid.
x, y = m(*np.meshgrid(lons,lats))
You try to get x,y from Basemap() instance, which is only one object. That's why it says that it expected 2 values (x, y), but got only one (Basemap()).
Related
I have a 2D array which I am trying to plot using plot_trisurf and I can't seem to make it work no matter what I try.
Here follows a minimally reproducible example where I am able to use plot_surface
import matplotlib.pyplot as plt
from matplotlib import cm
import numpy as np
frames = []
for _ in range(5):
matrix = np.array([
[np.random.normal(20, 3) for _ in range(6)]
for _ in range(6)
],
dtype = np.float32
)
frames.append(matrix)
fig= plt.figure(figsize = [6, 5], dpi = 100)
ax = fig.add_subplot(1, 1, 1, projection='3d')
ax.set_zlim(10, 30)
data = frames[0]
X, Y = np.meshgrid(
range(len(frames[0])),
range(len(frames[0][0]))
)
ax.plot_surface(X, Y, data, cmap=cm.Spectral, linewidth=1)
plt.show()
yielding
But when I try
ax.plot_trisurf(X, Y, data, cmap=cm.Spectral, linewidth=1)
I get an error that X and Y must be equal-length 1D arrays, so then I tried
ax.plot_trisurf(X.flatten(), Y.flatten(), data, cmap=cm.Spectral, linewidth=1)
But then I get the stacktrace
Command failed: python3 main.py
Traceback (most recent call last):
File "main.py", line 25, in
ax.plot_trisurf(X.flatten(), Y.flatten(), data, cmap=cm.Spectral, linewidth=1)
File "/usr/local/lib64/python3.8/site-packages/mpl_toolkits/mplot3d/axes3d.py", line 2051, in plot_trisurf
zt = z[triangles]
IndexError: index 6 is out of bounds for axis 0 with size 6
Does anyone know what I am doing wrong? I have tried many things and looked at the documentation, but can't seem to understand what I am missing.
Although it's a notebook question, but I am unable to get it correct, my problem is:
I have a function y ranging from 0 to 5.3 with 130 divisions
I have a function z ranging from 0 to 0.3 with 48 divisions
I wanted to plot a function v such that:
v = cos(2* \pi *z)*sin(\pi *y)
I tried to do with Python using the following code:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import math
y = np.arange(0, 5.3, 0.007692)
z = np.arange(0,0.3,0.021)
v = np.cos(2.0*math.pi*z)*np.sin(math.pi*y)
fig = plt.figure(figsize=(6, 6))
ax = fig.add_subplot(111, projection='3d')
ax.scatter( y, z, v,
linewidths=1, alpha=.7,
edgecolor='k',
s = 200,
c=v)
plt.show()
By looking at the problem or at the code itself it's clear that the array size of y and z are different and correspondingly the function "v" could not be evaluated correctly and thus I am getting the following error:
v = np.cos(2.0*math.pi*z)*np.sin(math.pi*y)
ValueError: operands could not be broadcast together with shapes (15,) (690,)
I am unable to get it fixed, also I tried to make different arrays for y and z and then using two different loops for y and z evaluated the value for function z, but again I could not do it correctly. Could any one please help.
Using useful comment by #tmdavison https://stackoverflow.com/users/588071/tmdavison I used the np.meshgrid I got the following contour, which is close to, what I was expecting, but is it possible to get the 3D plot of y,z,v ? The updated code is given as:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import math
y = np.arange(0, 5.3, 0.007692)
z = np.arange(0,0.3,0.021)
xx, yy = np.meshgrid(y, z, sparse=True)
v = np.cos(2.0*math.pi*xx)*np.sin(math.pi*yy)
h = plt.contourf(y,z,v)
plt.colorbar()
plt.show()
fig = plt.figure(figsize=(6, 6))
ax = fig.add_subplot(111, projection='3d')
ax.scatter( y, z, v,
linewidths=1, alpha=.7,
edgecolor='k',
s = 200,
c=v)
plt.show()
But it is giving me error which says:
ValueError: shape mismatch: objects cannot be broadcast to a single shape
I am trying to smoothen a lineplot with scipy.interpolate. However, for some reason I get an error with this method.
This my code:
import numpy as np
from scipy import interpolate
import matplotlib.pyplot as plt
x = np.array([1348.4256 , 1342.99776, 1345.86432, 1352.97024, 1353.09312, 1355.0304])
y = np.array([232.2108 , 233.60184, 236.09988, 235.40544, 235.51776, 238.42728])
smooth = interpolate.interp1d(x, y, 'cubic')
y_range = np.linspace(min(y), max(y), 20)
plt.plot(smooth(y_range), y_range)
plt.plot(x, y,
linewidth=1)
plt.plot(smooth(y_range),
y_range)
plt.show()
The error I get is TypeError: descriptor '_y_axis' for '_Interpolator1D' objects doesn't apply to 'interp1d' object
My question is: what can I do to resolve this error and get a smooth plot over this line?
Your smooth() function works fine within the limits of min(x) to max(x) and it returns y values for such operation. When you feed any value that falls beyond the limits, you will get error.
If you want to interpolate for x by specifying values of y, try this code:
smooth_for_y = interpolate.interp1d(y, x, 'cubic')
y_range = np.linspace(min(y), max(y), 20)
The interpolation:
smooth_for_y( y_range )
Output:
array([1348.4256 , 1344.64896129, 1342.64269324, 1342.09678777,
1342.70123678, 1344.14603221, 1346.12116596, 1348.31662995,
1350.4224161 , 1352.12851632, 1353.09777093, 1350.92268063,
1345.07380415, 1337.3796737 , 1329.67182218, 1323.78178249,
1321.54108752, 1324.78127019, 1335.33386338, 1355.0304 ])
Here is a possible solution based on some assumptions (mentioned in the code).
import numpy as np
from scipy import interpolate
import matplotlib.pyplot as plt
# raw data
x = np.array([1348.4256 , 1342.99776, 1345.86432, 1352.97024, 1353.09312, 1355.0304])
y = np.array([232.2108 , 233.60184, 236.09988, 235.40544, 235.51776, 238.42728])
smooth_for_y = interpolate.interp1d(x, y, 'cubic')
x_range = np.linspace(min(x), max(x), 20, endpoint=True)
y_smoothed = smooth_for_y( x_range )
# plot data as red dots
plt.scatter(x, y, linewidth=1, color="red")
# plot smoothed line across data
# assuming first point begins at xmin, ends at xmax, thus ...
# ignoring the sequence of the original data
plt.plot(x_range, y_smoothed)
plt.show()
The plot:
I am a new Python user and need help with plotting a heatmap in Python using matplotlib
I have three vectors [x, y, z], each having 7700 elements. I got the code for plotting the heatmap from google search (see below), but ended up with an error
Some pointers
In array "x", all the items are different
In array "y", not all the values are different
In array "z", not all the values are different
x = mdf_merged.get('Signal_x').samples # define the x array
y = mdf_merged.get('Signal_y').samples # define the y array
z = mdf_merged.get('Signal_z').samples # define the z array
x=np.unique(x)
x = np.unique(x)
y1, yind = np.unique(y, return_index=True)
X,Y = np.meshgrid(x,y[sorted(yind)])
Z=z.reshape(len(y1),len(x), order='F')
plt.pcolormesh(X,Y,Z)
plt.colorbar()
plt.xlabel("X-values")
plt.ylabel("Y-values")
I end up with this error
Traceback (most recent call last):
File "<input>", line 1, in <module>
ValueError: cannot reshape array of size 7700 into shape (6447,7700)
So my questions are
a) What could be the cause and possible solution to this ?
b) Why can't it directly take x, y, and z. Why do I have to do meshgrip and reshape ?
I am a newbie to Python so it could be nice with a little more detailed reply
So, with the help from the community, I have been able to reach closer to the solution. The thing that I did was
import numpy as np
from scipy.interpolate import griddata
import matplotlib.pyplot as plt
x = mdf_merged.get('VariableX').samples
y = mdf_merged.get('VariableY').samples
z = mdf_merged.get('VariableZ').samples
###
xi = np.linspace(min(x),max(x),10)
yi = np.linspace(min(y),max(y),20)
zi = griddata((x, y), z, (xi[None,:], yi[:,None]), method='linear')
plt.pcolormesh(xi, yi, zi)
I have two vectors that store my X, Y values than are lengths 81, 105 and then a (81,105) array (actually a list of lists) that stores my Z values for those X, Y. What would be the best way to plot this in 3d? This is what i've tried:
Z = np.load('Z.npy')
X = np.load('X.npy')
Y = np.linspace(0, 5, 105)
fig = plt.figure(figsize=(6,6))
ax = fig.add_subplot(111, projection='3d')
ax.plot_surface(X, Y, Z, cmap= 'viridis')
plt.show()
I get the following error : ValueError: shape mismatch: objects cannot be broadcast to a single shape
OK, I got it running. There is some tricks here. I will mention them in the codes.
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from random import shuffle
# produce some data.
x = np.linspace(0,1,81)
y = np.linspace(0,1,105)
z = [[i for i in range(81)] for x in range(105)]
array_z = np.array(z)
# Make them randomized.
shuffle(x)
shuffle(y)
shuffle(z)
# Match data in x and y.
data = []
for i in range(len(x)):
for j in range(len(y)):
data.append([x[i], y[j], array_z[j][i]])
# Be careful how you data is stored in your Z array.
# Stored in dataframe
results = pd.DataFrame(data, columns = ['x','y','z'])
# Plot the data.
fig = plt.figure(figsize=(6,6))
ax = fig.add_subplot(111, projection='3d')
ax.scatter(results.x, results.y, results.z, cmap= 'viridis')
The picture looks weird because I produced some data. Hope it helps.