How can a circle be drawn over a Seaborn plot? - python

I have a Seaborn Joinplot on which I want to draw an empty circle which will mark a certain diameter around the (0,0) point. Something like this:
How can it be done?

ax_joint.plot will do the job.
import matplotlib.pyplot as plt
import seaborn as sns
sns.set(style="white", color_codes=True)
tips = sns.load_dataset("tips")
a = sns.jointplot(x="total_bill", y="tip", data=tips)
a.ax_joint.plot([15],[3],'o',ms=60,mec='r',mfc='none')

I found the answer:
a = sns.jointplot(x=var_x, y=var_y, data=my_df)
a.ax_joint.plot([0],[0],'o',ms=60 , mec='r', mfc='none')

There is a dirty way to do it: generate the circle from equation and then plot that. I'm sure there are more sophisticated solutions, but I couldn't figure it out yet. This is by modifying the data of sns.JointGrid.
import seaborn as sns
import numpy as np
import matplotlib.pyplot as plt
sns.set(style="ticks")
R = 8 # radius
d = np.linspace(0,2*np.pi, 400) # some data to draw circle
def circle(d, r):
# x and y from the equation of a circle
return r*np.cos(d), r*np.sin(d)
rs = np.random.RandomState(11)
x = rs.gamma(2, size=1000)
y = -.5 * x + rs.normal(size=1000)
#graph your data
graph = sns.jointplot(x, y, kind="hex", color="#4CB391")
# creating the circle
a, b = circle(d, R)
#graphing it
graph.x = a
graph.y = b
graph.plot_joint(plt.plot)
plt.show()

Related

Plotting a log-log scale, log-binned network degree distributions on NetworkX

Trying to make a log-log scale log binned plot. Wondering if someone can give me some advice on how to approach this problem. Thanks.
import networkx as nx
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import powerlaw
G = nx.Graph()
G = nx.read_edgelist('data.txt', create_using=nx.DiGraph, nodetype = int)
M = nx.to_scipy_sparse_matrix(G)
xmin = min([d[1] for d in G.degree()])
indegrees = M.sum(0).A[0]
degree = np.bincount(indegrees)
fit = powerlaw.Fit(np.array(degree)+1, fit_method='KS')
fig = plt.figure(figsize=(16, 6))
plt.subplot(1, 3, 1)
plt.plot(range(len(degree)),degree,'b.')
plt.loglog()
plt.xlim((min(degree), max(degree)))
plt.xlabel('Degree')
plt.ylabel('P(k)')
plt.show()
What I current have
What I am trying to get

Plotting spheres of radius R

How can we make spheres of radius R centered at given coordinates(x,y,z). Like if there are 10 set of coordinates for the centers of the spheres and correspondingly 10 different values of the radii. How can we plot it in python ? Is there any way to do this in python ,like in MATLAB this can be done using surf command. In python how can we achieve this ?
This will solve your problem
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
import numpy as np
list_center = [(1,2,3),(-4,-5,6), (5,5,6)]
list_radius = [1,2,1]
def plt_sphere(list_center, list_radius):
for c, r in zip(list_center, list_radius):
ax = fig.gca(projection='3d')
# draw sphere
u, v = np.mgrid[0:2*np.pi:50j, 0:np.pi:50j]
x = r*np.cos(u)*np.sin(v)
y = r*np.sin(u)*np.sin(v)
z = r*np.cos(v)
ax.plot_surface(x-c[0], y-c[1], z-c[2], color=np.random.choice(['g','b']), alpha=0.5*np.random.random()+0.5)
fig = plt.figure()
plt_sphere(list_center, list_radius)

Plotting an ellipse but ellipse is not showing up

I am attempting to plot an ellipse surrounding scattered data points, but when the pyplot displays my plot only the data points are showing up and ellipse isn't. Do I need to install the patch somehow?
Here is my code:
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as pp
import numpy as np
from matplotlib import cm
import pandas as pd
from matplotlib.patches import Ellipse
data_to_plot = pd.read_csv("positions.csv", sep = ",", index_col=False)
xs = data_to_plot['x']
ys = data_to_plot['y']
zs = data_to_plot['z']
covxy = np.cov(xs, ys)
lambda_xy, vxy = np.linalg.eig(covxy)
lambda_xy = np.sqrt(lambda_xy)
ax1 = pp.subplot(221)
for j in xrange(1, 4):
ell = Ellipse(xy=(xav, yav),
width=lambda_xy[0]*j*2, height=lambda_xy[1]*j*2,
angle=-np.rad2deg(np.arccos(vxy[0, 0])))
ell.set_facecolor('none')
ax1.add_artist(ell)
ax1.set_xlabel("x distance from the sun / AU")
ax1.set_ylabel("y distance from the sun / AU")
pp.scatter(xs, ys)
pp.xlim(xav-0.001,xav+0.0013)
pp.ylim(yav-0.001,yav+0.001)
ell.set_facecolor('none') seems counterproductive. If the intention is to show the ellipse, it should not have 'none' as color. Or it should have at least an edgecolor being set, e.g.
ell.set_edgecolor("limegreen")
Or consider giving the colors as arguments to the ellipse
Ellipse(..., fc="none", ec="limegreen")

Partial shade of distribution plot using Seaborn

Following simple code:
import numpy as np
import seaborn as sns
dist = np.random.normal(loc=0, scale=1, size=1000)
ax = sns.kdeplot(dist, shade=True);
Yields the following image:
I would like to only shade everything right (or left to some x value). What is the simplest way? I am ready to use something other than Seaborn.
After calling ax = sns.kdeplot(dist, shade=True), the last line in ax.get_lines() corresponds to the kde density curve:
ax = sns.kdeplot(dist, shade=True)
line = ax.get_lines()[-1]
You can extract the data corresponding to that curve using line.get_data:
x, y = line.get_data()
Once you have the data, you can, for instance, shade the region corresponding to x > 0 by selecting those points and calling ax.fill_between:
mask = x > 0
x, y = x[mask], y[mask]
ax.fill_between(x, y1=y, alpha=0.5, facecolor='red')
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
dist = np.random.normal(loc=0, scale=1, size=1000)
ax = sns.kdeplot(dist, shade=True)
line = ax.get_lines()[-1]
x, y = line.get_data()
mask = x > 0
x, y = x[mask], y[mask]
ax.fill_between(x, y1=y, alpha=0.5, facecolor='red')
plt.show()
Using seaborn is often fine for standard plots, but when some customized requirements come into play, falling back to matplotlib is often easier.
So one may first calculate the kernel density estimate and then plot it in the region of interest.
import scipy.stats as stats
import numpy as np
import matplotlib.pyplot as plt
plt.style.use("seaborn-darkgrid")
dist = np.random.normal(loc=0, scale=1, size=1000)
kde = stats.gaussian_kde(dist)
# plot complete kde curve as line
pos = np.linspace(dist.min(), dist.max(), 101)
plt.plot(pos, kde(pos))
# plot shaded kde only right of x=0.5
shade = np.linspace(0.5,dist.max(), 101)
plt.fill_between(shade,kde(shade), alpha=0.5)
plt.ylim(0,None)
plt.show()

Putting matplotlib hexbin into an Aitoff projection

I have the nice hexbin plot below, but I'm wondering if there is any way to get hexbin into an Aitoff projection? The salient code is:
import numpy as np
import math
import matplotlib.pyplot as plt
from astropy.io import ascii
filename = 'WISE_W4SNRge3_and_W4MPRO_lt_6.0_RADecl_nohdr.dat'
datafile= path+filename
data = ascii.read(datafile)
points = np.array([data['ra'], data['dec']])
color_map = plt.cm.Spectral_r
points = np.array([data['ra'], data['dec']])
xbnds = np.array([ 0.0,360.0])
ybnds = np.array([-90.0,90.0])
extent = [xbnds[0],xbnds[1],ybnds[0],ybnds[1]]
fig = plt.figure(figsize=(6, 4))
ax = fig.add_subplot(111)
x, y = points
gsize = 45
image = plt.hexbin(x,y,cmap=color_map,
gridsize=gsize,extent=extent,mincnt=1,bins='log')
counts = image.get_array()
ncnts = np.count_nonzero(np.power(10,counts))
verts = image.get_offsets()
ax.set_xlim(xbnds)
ax.set_ylim(ybnds)
plt.xlabel('R.A.')
plt.ylabel(r'Decl.')
plt.grid(True)
cb = plt.colorbar(image, spacing='uniform', extend='max')
plt.show()
and I've tried:
plt.subplot(111, projection="aitoff")
before doing the plt.hexbin command, but which only gives a nice, but blank, Aitoff grid.
The problem is that the Aitoff projection uses radians, from -π to +π. Not degrees from 0 to 360. I use the Angle.wrap_at function to achieve this, as per this Astropy example (which essentially tells you how to create a proper Aitoff projection plot).
In addition, you can't change the axis limits (that'll lead to an error), and shouldn't use extent (as ImportanceOfBeingErnest's answer also states).
You can change your code as follows to get what you want:
import numpy as np
import matplotlib.pyplot as plt
from astropy.io import ascii
from astropy.coordinates import SkyCoord
from astropy import units
filename = 'WISE_W4SNRge3_and_W4MPRO_lt_6.0_RADecl_nohdr.dat'
data = ascii.read(filename)
coords = SkyCoord(ra=data['ra'], dec=data['dec'], unit='degree')
ra = coords.ra.wrap_at(180 * units.deg).radian
dec = coords.dec.radian
color_map = plt.cm.Spectral_r
fig = plt.figure(figsize=(6, 4))
fig.add_subplot(111, projection='aitoff')
image = plt.hexbin(ra, dec, cmap=color_map,
gridsize=45, mincnt=1, bins='log')
plt.xlabel('R.A.')
plt.ylabel('Decl.')
plt.grid(True)
plt.colorbar(image, spacing='uniform', extend='max')
plt.show()
Which gives
I guess your problem lies in the use of the extent which is set to something other than the range of the spherical coordinate system.
The following works fine:
import matplotlib.pyplot as plt
import numpy as np
ra = np.linspace(-np.pi/2.,np.pi/2.,1000)
dec = np.sin(ra)*np.pi/2./2.
points = np.array([ra, dec])
plt.subplot(111, projection="aitoff")
color_map = plt.cm.Spectral_r
x, y = points
gsize = 45
image = plt.hexbin(x,y,cmap=color_map,
gridsize=45,mincnt=1,bins='log')
plt.xlabel('R.A.')
plt.ylabel(r'Decl.')
plt.grid(True)
cb = plt.colorbar(image, spacing='uniform', extend='max')
plt.show()

Categories

Resources