I want to change the the look of the mean in violinplots. I am using matplotlib. I could change the color of the means with the following code:
import matplotlib.pyplot as plt
fig,(axes1,axes2,axes3) = plt.subplots(nrows=3,ncols=1,figsize=(10,20))
r=axes2.violinplot(D,showmeans=True,showmedians=True)
r['cmeans'].set_color('red')
But now I want to change the look of the mean (currently a line, like the median) to a 'small circle'.
Can someone help me with this?
The idea can be to obtain the coordinates of the mean lines and plot a scatter plot at those coordinates.
Obtaining the coordinates can
either be done by looping over the mean lines' paths,
# loop over the paths of the mean lines
xy = [[l.vertices[:,0].mean(),l.vertices[0,1]] for l in r['cmeans'].get_paths()]
xy = np.array(xy)
or by reacalculating the mean from the input data.
#alternatively get the means from the data
y = data.mean(axis=0)
x = np.arange(1,len(y)+1)
xy=np.c_[x,y]
Complete code:
import matplotlib.pyplot as plt
import numpy as np; np.random.seed(1)
data = np.random.normal(size=(50, 2))
fig,ax = plt.subplots()
r=ax.violinplot(data,showmeans=True)
# loop over the paths of the mean lines
xy = [[l.vertices[:,0].mean(),l.vertices[0,1]] for l in r['cmeans'].get_paths()]
xy = np.array(xy)
##alternatively get the means from the data
#y = data.mean(axis=0)
#x = np.arange(1,len(y)+1)
#xy=np.c_[x,y]
ax.scatter(xy[:,0], xy[:,1],s=121, c="crimson", marker="o", zorder=3)
# make lines invisible
r['cmeans'].set_visible(False)
plt.show()
Related
I want to extract polar coordinates from the plot. There exists a matrix that has 10 rows and 2 columns a and b. This matrix has the numbers that created the polar plot.
But what I am looking for is a matrix that has the polar coordinates that are already plotted.
Example: the first row (meaning, information about the first point) would include the x,y,radius and theta/angle or any other useful information from the plot that were previously not there in the original matrix.
Think of polar plotting as a transformation that was implemented on the matrix in the for loop and I want to extract the new numbers resulted from the output polar plot.
import matplotlib.pyplot as plt
sample= [1,2,3,4,5,6,7,8,9,10]
fig = plt.figure()
fig.add_subplot(111, projection='polar')
data = sample
for i in data:
a=i+min(data)
b=i+max(data)
plt.polar(a,b, '.', c='black')
plt.show()
Even after your clarification I am a little confused by the code example. But I am pretty sure the code below answers your question.
import numpy as np
import matplotlib.pyplot as plt
x = np.random.random((10,1)) # same as "a" in your example
y = np.random.random((10,1)) # same as "b" in your example
plt.plot(x,y)
plt.title("Rectangular coordinates")
plt.show()
th = np.arctan2(y,x)
r = np.sqrt(x**2 + y**2)
# Should show the same plot as above, just with different margins/aspect ratio/grid lines
plt.polar(th,r)
plt.title("Polar coordinates")
plt.show()
It's just as easy to go in reverse, getting the rectangular coordinates if you assume your random data is representing data in polar coordinates.
I've tried to recreate the image attached using cmaps as well as with if/else statements.
My current attempt is based upon the advice given in this thread
I tried using 1.8<=x<=2.2 but I get an error.
Here is my current code below:
import numpy as np
import matplotlib.pyplot as plt
N = 500
# center, variation, number of points
x = np.random.normal(2,0.2,N)
y = np.random.normal(2,0.2,N)
colors = np.where(x<=2.2,'r',np.where(y<=2.2,'b','b'))
plt.scatter(x , y, c=colors)
plt.colorbar()
plt.show()
To make that plot, you need to pass an array with the color of each point. In this case the color is the distance to the point (2, 2), since the distributions are centered on that point.
import numpy as np
import matplotlib.pyplot as plt
N = 500
# center, variation, number of points
x = np.random.normal(2,0.2,N)
y = np.random.normal(2,0.2,N)
# we calculate the distance to (2, 2).
# This we are going to use to give it the color.
color = np.sqrt((x-2)**2 + (y-2)**2)
plt.scatter(x , y, c=color, cmap='plasma', alpha=0.7)
# we set a alpha
# it is what gives the transparency to the points.
# if they suppose themselves, the colors are added.
plt.show()
I read a waveform from an oscilloscope. The waveform is divided into 10 segments as a function of time. I want to plot the complete waveform, one segment above (or under) another, 'with a vertical offset', so to speak. Additionally, a color map is necessary to show the signal intensity. I've only been able to get the following plot:
As you can see, all the curves are superimposed, which is unacceptable. One could add an offset to the y data but this is not how I would like to do it. Surely there is a much neater way of plotting my data? I've tried a few things to solve this issue using pylab but I am not even sure how to proceed and if this is the right way to go.
Any help will be appreciated.
import readTrc #helps read binary data from an oscilloscope
import matplotlib.pyplot as plt
fName = r"...trc"
datX, datY, m = readTrc.readTrc(fName)
segments = m['SUBARRAY_COUNT'] #number of segments
x, y = [], []
for i in range(segments+1):
x.append(datX[segments*i:segments*(i+1)])
y.append(datY[segments*i:segments*(i+1)])
plt.plot(x,y)
plt.show()
A plot with a vertical offset sounds like a frequency trail.
Here's one approach that does just adjust the y value.
Frequency Trail in MatPlotLib
The same plot has also been coined a joyplot/ridgeline plot. Seaborn has an implementation that creates a series of plots (FacetGrid), and then adjusts the offset between them for a similar effect.
https://seaborn.pydata.org/examples/kde_joyplot.html
An example using a line plot might look like:
import seaborn as sns
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
segments = 10
points_per_segment = 100
#your data preparation will vary
x = np.tile(np.arange(points_per_segment), segments)
z = np.floor(np.arange(points_per_segment * segments)/points_per_segment)
y = np.sin(x * (1 + z))
df = pd.DataFrame({'x': x, 'y': y, 'z': z})
pal = sns.color_palette()
g = sns.FacetGrid(df, row="z", hue="z", aspect=15, height=.5, palette=pal)
g.map(plt.plot, 'x', 'y')
g.map(plt.axhline, y=0, lw=2, clip_on=False)
# Set the subplots to overlap
g.fig.subplots_adjust(hspace=-.00)
g.set_titles("")
g.set(yticks=[])
g.despine(bottom=True, left=True)
plt.show()
Out:
I have 2 lists tab_x (containe the values of x) and tab_z (containe the values of z) which have the same length and a value of y.
I want to plot a 3D curve which is colored by the value of z. I know it's can be plotted as a 2D plot but I want to plot a few of these plot with different values of y to compare so I need it to be 3D.
My tab_z also containe negatives values
I've found the code to color the curve by time (index) in this question but I don't know how to transforme this code to get it work in my case.
Thanks for the help.
I add my code to be more specific:
fig8 = plt.figure()
ax8 = fig8.gca(projection = '3d')
tab_y=[]
for i in range (0,len(tab_x)):
tab_y.append(y)
ax8.plot(tab_x, tab_y, tab_z)
I have this for now
I've tried this code
for i in range (0,len(tab_t)):
ax8.plot(tab_x[i:i+2], tab_y[i:i+2], tab_z[i:i+2],color=plt.cm.rainbow(255*tab_z[i]/max(tab_z)))
A total failure:
Your second attempt almost has it. The only change is that the input to the colormap cm.jet() needs to be on the range of 0 to 1. You can scale your z values to fit this range with Normalize.
import numpy as np
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import colors
fig = plt.figure()
ax = fig.gca(projection='3d')
N = 100
y = np.ones((N,1))
x = np.arange(1,N + 1)
z = 5*np.sin(x/5.)
cn = colors.Normalize(min(z), max(z)) # creates a Normalize object for these z values
for i in xrange(N-1):
ax.plot(x[i:i+2], y[i:i+2], z[i:i+2], color=plt.cm.jet(cn(z[i])))
plt.show()
I am trying to plot a lognormal distribution so I can compare it with a histogram of my sample data using the code below but my plot does not look right. Is there something with my code that I am not doing correctly?
The C array has a length of 17576
import matplotlib.pyplot as plt
import numpy as np
data=np.loadtxt(F)
C=data[:,3]
x = np.ma.log(C)
avg = np.mean(x)
std = np.std(x)
dist=lognorm(std,loc=avg)
plt.plot(C,dist.pdf(C),'r')
plt.show()
It looks like your x data are not in sorted order. Try this
ind = np.argsort(C)
xx = C[ind]
yy = dist.pdf(C)[ind]
plt.plot(xx, yy, 'r')
Plot just connects all the (x,y) pairs with straight lines, so you need to make sure you trace your function from left-right (or right-left). Alternatively, you can skip the lines between the plot:
plt.plot(C, dist.pdf(C), 'ro')