Strange output in matplotlib - python

Can someone explain why I get this strange output when running this code:
import matplotlib.pyplot as plt
import numpy as np
def x_y():
return np.random.randint(9999, size=1000), np.random.randint(9999, size=1000)
plt.plot(x_y())
plt.show()
The output:

Your data is a tuple of two 1000 length arrays.
def x_y():
return np.random.randint(9999, size=1000), np.random.randint(9999, size=1000)
xy = x_y()
print(len(xy))
# > 2
print(xy[0].shape)
# > (1000,)
Let's read pyplot's documentation:
plot(y) # plot y using x as index array 0..N-1
Thus pyplot will plot a line between (0, xy[0][i]) and (1, xy[1][i]), for i in range(1000).
You probably try to do this:
plt.plot(*x_y())
This time, it will plot 1000 points joined by lines: (xy[0][i], xy[1][i]) for i in range 1000.
Yet, the lines don't represent anything here. Therefore you probably want to see individual points:
plt.scatter(*x_y())

Your function x_y is returning a tuple, assigning each element to a variable gives the correct output.
import matplotlib.pyplot as plt
import numpy as np
def x_y():
return np.random.randint(9999, size=1000), np.random.randint(9999, size=1000)
x, y = x_y()
plt.plot(x, y)
plt.show()

Related

Hist chart from list

import matplotlib as plp
cube = []
z = 0
while not z == 50:
x = random.randint(1, 6)
cube.append(x)
z = z + 1
print(cube)
plp.plot(cube[1])
plp.show()
How to repair this code to show histogram from components include in my list cube?
The comments do make some suggestions on most of the fixes you can make, but you can also improve this code alot in other ways. Here is what I would propose:
import matplotlib.pyplot as plt
import random
cube = []
for _ in range(50):
x = random.randint(1, 6)
cube.append(x)
plt.hist(cube)
plt.show()
First, since you only use z as an iteration counter, a for loop is better here (though the while loop will still work, it is more error prone). I also changed plp to plt, you don't have to do this but this is the convention. You can then use plt.hist(cube) to plot a histogram.
Note that if you want to use numpy, you can make this even simpler:
import matplotlib.pyplot as plt
import numpy as np
cube = np.random.randint(1, 6, size=50)
plt.hist(cube)
plt.show()
Since numpy lets you specify the size of the array of random numbers you want.

Something wrong about matplotlib.pyplot.contour

I used matplotlib.pyplot.contour to draw a line, but the result is strange.
My python code:
import numpy as np
from matplotlib import pyplot as plt
N = 1000
E = np.linspace(-5,0,N)
V = np.linspace(0, 70,N)
E, V = np.meshgrid(E, V)
L = np.sqrt(-E)
R = -np.sqrt(E+V)/np.tan(np.sqrt(E+V))
plt.contour(V, E,(L-R),levels=[0])
plt.show()
The result is:
But when I use Mathematica, the result is different.
Mathematica code is:
ContourPlot[Sqrt[-en] == -Sqrt[en + V]/Tan[Sqrt[en + V]], {V, 0, 70}, {en, -5, 0}]
The result is:
The result that I want is Mathematica's result.
Why does matplotlib.pyplot.contour give the wrong result? I am very confused!
It would be very appreciate if you can give me some idea! Thank you very much!
The result given by matplotlib.pyplot.contour is numerically correct, but mathematically wrong.
Check what happens if you simply plot the tan(x):
import numpy as np
from matplotlib import pyplot as plt
x = np.linspace(0,2*np.pi,1000)
y = np.tan(x)
plt.plot(x,y)
plt.show()
You will get a line at the poles. This is because subsequent points are connected.
You can circumvent this by using np.inf for points larger than a certain number. E.g. adding
y[np.abs(y)> 200] = np.inf
would result in
The same approach can be used for the contour.
import numpy as np
from matplotlib import pyplot as plt
N = 1000
x = np.linspace(0, 70,N)
y = np.linspace(-5,0,N)
X,Y = np.meshgrid(x, y)
F = np.sqrt(-Y) + np.sqrt(Y+X)/np.tan(np.sqrt(Y+X))
F[np.abs(F) > 200] = np.inf
plt.contour(X, Y, F, levels=[0])
plt.show()

Plot shows wrong points in Jupyter

I'm doing a Python test to draw some functions.
The problem is that the points that both functions intersect at the same X are not correct.
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
x = np.arange(-10,10,1)
def f(x):
return x+30
def z(x):
return x*x
plt.figure(figsize=(5,5))
plt.plot(x, f(x).astype(np.int))
plt.plot(x, z(x).astype(np.int))
plt.title("Gráfico de función" )
plt.xlabel("X")
plt.ylabel("Y")
idx = np.argwhere(np.diff(np.sign(f(x) - z(x)))).flatten()
plt.plot(x[idx], f(x[idx]), 'ro')
plt.legend(["F","Z"])
plt.show()
I expect only two points, but in the plot appeared four. Two of them are incorrect.
This error is not with the plot itself but with your methods of getting the points for this case when the intersection is an integer value. When taking np.diff of np.sign you go from -1 to 0 to 1 at the intersection points giving you 1 at 4 locations. If the intersection was not an int, you would get -1 to 1 and get the correct answer. If you try this instead you can find the integer intersection points:
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
x = np.arange(-10,10,1)
def f(x):
return x+30.
def z(x):
return x*x
plt.figure(figsize=(5,5))
plt.plot(x, f(x).astype(np.int))
plt.plot(x, z(x).astype(np.int))
plt.xlabel("X")
plt.ylabel("Y")
#Say only get args where there is no sign (i.e. zero).
idx = np.argwhere((np.sign(f(x) - z(x))==0))
plt.plot(x[idx], f(x[idx]), 'ro')
plt.legend(["F","Z"])
plt.show()
EDIT:
The above code only works if you have perfect integer intersections. To arbitrarily do both you need to check to see if a perfect integer intersection exists before deciding which method to use. I just used a simple for loop to do this but I am sure there are more elegant ways to do this.
for v in np.sign(f(x) - z(x)):
if v==0:
idx = np.argwhere(np.sign(f(x) - z(x))==0)
break
else:
idx = np.argwhere(np.diff(np.sign(f(x) - z(x))))

How do I plot with x-axis scaled down by a fixed quantity?

Say I have the following code:
import random
import matplotlib.pyplot as plt
lis = random.sample(range(1, 5000), 4000)
plt.plot(lis)
This plots the following:
The x-axis is printed from 0 to 4000 with a step size of 1. But I want it to be 0 to 4 with a step size of 0.0001.
I tried this:
import random
import numpy as np
import matplotlib.pyplot as plt
lis = random.sample(range(1, 5000), 4000)
plt.plot(lis)
plt.xlabel(np.linspace(0, 4, num=40001))
But this does not do the job:
How do I do this?
plt.plot() can take only one array as an argument (i.e. plt.plot(y)), then it interprets it as y values and plots it simply over the indices, as in your example. But if you want different x values, you can simply put them before the y values in the argument list like plt.plot(x, y), with x being your x value array, which obviuosly should have the same length as y.
In your case this would mean
import numpy as np
import matplotlib.pyplot as plt
lis = np.random.randint(0, 5000, 4000)
x = np.arange(0, 4, 0.001)
plt.plot(x, lis)
See the docs for further reading: https://matplotlib.org/api/_as_gen/matplotlib.pyplot.plot.html

matplotlib 3d wireframe plot

Right, so I've got a list of x values, y values and z values (which I think I converted into arrays?) which I want to make a surface plot, but it's not working.
Here's what I'm trying to do, you can ignore most of the code as it is pretty irrelevant - just look at the end where I have xdis, ydis and dist and where I'm trying to plot atm I'm getting ValueError: need more than 1 value to unpack :(. Help much appreciated.
from math import *
from numpy import *
import pylab
def sweep (v,p,q,r,s):
a=.98
for i in range (1, len(v)-1):
for j in range (1, len(v)-1):
c =0.0
if i==p and j==q: c =1.0
if i==r and j==s: c= -1.0
v[i,j]=(v[i -1,j]+v[i+1,j]+v[i,j -1]+v[i,j+1]+c-a*v[i,j])/(4-a)
def main():
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FormatStrFormatter
import matplotlib.pyplot as plt
ydis=[]
xdis=[]
resis=[]
for j in range(2,18):
for i in range(2,18):
v= zeros ((20,20),float )
p=q=9
r=i
s=j
dv =1.0e10
lastdv =0
count =0
while (fabs(dv - lastdv)>1.0e-7*fabs(dv)):
lastdv =dv
sweep(v,p,q,r,s)
dv=v[p,q]-v[r,s]
resis.append(dv)
xdis.append(r-p)
ydis.append(s-q)
X=array(xdis)
Y=array(ydis)
Z=array(resis)
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot_wireframe(X,Y,Z)
plt.show()
main()
plot_wireframe expects three 2D-arrays (X,Y,Z) as input. So,
after:
X=np.array(xdis)
Y=np.array(ydis)
Z=np.array(resis)
add:
X=X.reshape((-1,16))
Y=Y.reshape((-1,16))
Z=Z.reshape((-1,16))
It doesn't seem like the "sweep" function is modifying 'v' so you're getting an empty list.

Categories

Resources