Related
I am trying to prepare a box and scatter plot for 8 data points in python. I use the following code:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
x = [24.4, 6.7, 19.7, 16.0, 25.1, 19.5, 10, 22.1]
f, ax = plt.subplots()
ax.boxplot(x, vert=False, showmeans=True, showfliers=False)
x0 = np.random.normal(1, 0.05, len(x))
c = ['r', 'b', 'c', 'm', 'y', 'g', 'm', 'k']
lab = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']
ax.scatter(x, x0, c=c, s=60, alpha=0.2)
ax.legend(labels=lab, loc="upper left", ncol=8)
It generate a image like the following:
It looks that the legend doesn't have the proper sphere symbols with different colors, which I expected. Beside the colors for the symbols are shallow and light.
So how to generate proper legends with correct symbols and how to make the colors of the symbols brighter and sharper?
I will deeply appreciate it if anyone can help.
Best regards
To make the colours brighter, just raise the alpha value.
For the legend, the order of the plotting matters here, it is better that the boxplot is plotted after the scatter plots. Also, to get for each point a place in the legend, it should b considered as a different graph, for that I used a loop to loop over the values of x, x0 and c. Here's the outcome:
import numpy as np
import matplotlib.pyplot as plt
# init figure
f, ax = plt.subplots()
# values
x = [24.4, 6.7, 19.7, 16.0, 25.1, 19.5, 10, 22.1]
x0 = np.random.normal(1, 0.05, len(x))
# labels and colours
c = ['r', 'b', 'c', 'm', 'y', 'g', 'm', 'k']
lab = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']
# put the plots into a list
plots = []
for i in range(len(x)):
p = ax.scatter(x[i], x0[i], c=c[i], s=60, alpha=0.5) # raised the alpha to get sharper colors
plots.append(p)
# plot legends
plt.legend(plots,
labels=lab,
scatterpoints=1,
loc='upper left',
ncol=8,
fontsize=8)
# plot the box plot (the order here matters!)
ax.boxplot(x, vert=False, showmeans=True, showfliers=False)
# save the desired figure
plt.savefig('tt.png')
Output:
Let's consider one weighted undirected graph G.
Has Networkx an optimised method to get the number of nodes and edges of each subgraph connected to one focused node?
import networkx as nx
import matplotlib.pyplot as plt
listcolor = ['darkblue', 'blue', 'darkred', 'red', 'darkgreen', 'lime', 'gold', 'yellow', 'darkslateblue', 'darkorchid', 'darkorange', 'orange']
G = nx.Graph()
G.add_edge('A', 'B', weight= 1)
G.add_edge('A', 'J', weight= 2)
G.add_edge('K', 'L', weight= 4)
G.add_edge('E', 'F', weight= 7)
G.add_edge('I', 'J', weight= 8)
G.add_edge('B', 'K', weight= 9)
G.add_edge('B', 'E', weight= 17)
G.add_edge('A', 'C', weight= 19)
G.add_edge('H', 'K', weight= 19)
G.add_edge('G', 'H', weight= 20)
G.add_edge('D', 'H', weight= 22)
pos = nx.spring_layout(G, seed=2)
nx.draw(G,node_color = listcolor, with_labels = True)
plt.tight_layout()
plt.axis("off")
plt.show()
For example, let's consider the node B: it has three subgraphs connected, one with 5 nodes (including K,L,D,H,G), one with 4 nodes (including C,A,J,I) and one with 2 nodes (including F,E). Now, imagine I need to get the same list of subgraphs and for each its number of nodes, whatever the considered node (K for another example). How to get this list of subgraphs and their number of nodes and edges efficiently from G?
Thank to Paul Brodersen which showed me the way to this solution with his rapid comment:
import networkx as nx
import matplotlib.pyplot as plt
import copy
def GetSubGAtt(g,fn): # get subgraphs attributes : g: a graph, fn: focal node
wg = copy.deepcopy(g) # working graph
wg.remove_node(fn)
LSubG = list(nx.connected_components(wg)) # get the subgraphs
dictr = {} # a dict of results {neighbor node:number of nodes in its subgraph}
neig = list(g.adj[fn]) # get the neighbors
for i,j in enumerate(LSubG):
l=len(j)
k=set(neig) & set(j)
dictr[list(k)[0]]=len(j)
return dictr
listcolor = ['darkblue', 'blue', 'darkred', 'red', 'darkgreen', 'lime', 'gold', 'yellow', 'darkslateblue', 'darkorchid', 'darkorange', 'orange']
G = nx.Graph()
G.add_edge('A', 'B', weight= 1)
G.add_edge('A', 'J', weight= 2)
G.add_edge('K', 'L', weight= 4)
G.add_edge('E', 'F', weight= 7)
G.add_edge('I', 'J', weight= 8)
G.add_edge('B', 'K', weight= 9)
G.add_edge('B', 'E', weight= 17)
G.add_edge('A', 'C', weight= 19)
G.add_edge('H', 'K', weight= 19)
G.add_edge('G', 'H', weight= 20)
G.add_edge('D', 'H', weight= 22)
result = GetSubGAtt(G,'B')
print(result)
GetSubGAtt() returns a dictionary of the subgraph connected to one focal node and the number of nodes in these subgraphs.
I am testing a very simple exercise just plot the code below:
t = pd.Series([1,2,5,1,8], index=['a', 's', 'l', 'f', 'd' ])
t.plot(linestyle = '-', color = 'b', sharex = True)
but I cannot see the letters a, s, l, f, and d.
Any suggestions?
You can go like:
import pandas as pd
from matplotlib import pyplot as plt
t = pd.Series([1,2,5,1,8], index=['a', 's', 'l', 'f', 'd' ])
plt.plot(t.index, t.values,linestyle = '-', color = 'b')
plt.show()
Image is in the following link
Adapted from here
I want to make a pie chart using matplotlib. I am using python 2.7. I am trying to recreate the example given here with inputs from this stackoverflow post. But, I keep running into errors.
This is my code:
import matplotlib.pyplot as plt
topic = ['A', 'B', 'C', 'D', \
'E', 'F', 'G', 'H', 'I' \
'J']
labels = list(topic)
sizes = [18.7, 18.4, 12.7, 8.5, 3.4, 2.4, 1.8, 1.7, 1.5, 30.9]
explode = (0, 0.1, 0, 0, 0, 0, 0, 0, 0, 0) # only "explode" the 2nd slice (i.e. 'Hogs')
fig1, ax1 = plt.subplots()
ax1.pie(sizes, explode=explode, labels=labels,
autopct='%1.1f%%',
shadow=True, startangle=90)
ax1.axis('equal')
plt.show()
This is the error that I am getting:
Traceback (most recent call last):
File "occupation_pie.py", line 13, in <module>
shadow=True, startangle=90)
File "/anaconda2/lib/python2.7/site-packages/matplotlib/__init__.py", line 1867, in inner
return func(ax, *args, **kwargs)
File "/anaconda2/lib/python2.7/site-packages/matplotlib/axes/_axes.py", line 2867, in pie
raise ValueError("'label' must be of length 'x'")
ValueError: 'label' must be of length 'x'
How can I make my code work?
Is it on purpose that you are missing a , in topics?
Try changing topic = ['A', 'B', 'C', 'D', \
'E', 'F', 'G', 'H', 'I' \
'J']
to
topic = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J']
I have developed a bit of code to automatically generate an equilateral n-dimensional polygon:
# Create equilateral n-dimensional polygon
def polygon(side, radius=1, rotation=0, translation=None):
import math
vertex = 2 * math.pi / side
points = [
(math.sin(vertex * i + rotation) * radius,
math.cos(vertex * i + rotation) * radius)
for i in range(side)]
if translation:
points = [[sum(pair) for pair in zip(point, translation)]
for point in points]
return np.array(points)
Now, I want to put labels neatly to the outside corners of this n-dimensional polygon. In the following example I have created a hexagon with radius 10, centered around (3,3).
import matplotlib.pyplot as plt
pol = polygon(7, 10, 0, [3,3])
hull = ConvexHull(pol)
labels = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', "L", 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
fig = plt.figure(figsize=(4, 4), dpi=100)
for simplex in hull.simplices:
plt.plot(pol[simplex,0], pol[simplex,1], 'k-')
plt.plot(pol[:,0], pol[:,1], 'gs', ms=10)
if labels is not None:
for i, label in enumerate(labels):
if i <= len(pol)-1:
plt.annotate(label, xy=(pol[:,0][i],pol[:,1][i]), xytext=(0, 8),
textcoords='offset points', ha="center", va="bottom")
plt.axis('off')
plt.show()
Unfortunately, as the figure shows, only point A, B, and F lay neatly outside the hexagon. Is there a systematic way to annotate the labels to the outside corner of the polygon (hexagon in this case), no matter the dimension n? Thanks in advance!
Plot of hexagon with wrongly placed annotations
First, let's look at the special case of a n-dimensional regular polygon.
For this, you can just put the annotations on the vertices of a slightly larger polygon (I used 1.2 times the original radius).
Below is the full code and result.
import matplotlib.pyplot as plt
from scipy.spatial import ConvexHull
r = 10 # radius
center = [3, 3]
pol = polygon(7, r, 0, center)
pol2 = polygon(7, 1.2*r, 0, center) # for annotations
hull = ConvexHull(pol)
labels = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', "L", 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
fig = plt.figure(figsize=(4, 4), dpi=100)
for simplex in hull.simplices:
plt.plot(pol[simplex,0], pol[simplex,1], 'k-')
plt.plot(pol[:,0], pol[:,1], 'gs', ms=10)
if labels is not None:
for i, label in enumerate(labels):
if i <= len(pol)-1:
plt.annotate(label, xy=(pol2[i,0], pol2[i,1]), xytext=(0, 0),
textcoords='offset points', ha="center", va="center")
plt.xlim(center[0] - 1.5*r, center[0] + 1.5*r)
plt.ylim(center[1] - 1.5*r, center[1] + 1.5*r)
plt.axis('off')
plt.show()
Now, let's look at a general convex hull. An easy solution would be the following:
For each simplex S, calculate the mid point M of its neighbouring two simplices (called N_1 and N_2). We know this midpoint must be in the interior of the convex hull.
(N_1, N_2) = hull.neighbors(S)
M = (pol[N_1] + pol[N_2]) / 2
Draw the line from M to S, and take the new point M_ext which is on the line, so that S is equidistant to M and M_ext, but with M_ext being on the other side. We know that M_ext is definitely, in that case.
M_ext = pol[S] + (pol[S] - M)
You could potentially normalize it, so that the annotations are the same distance to the simplex (e.g. using numpy.linalg.norm). In my code I also multiplied by a constant factor, so that the text does not overlap with the vertices.
M_ext = pol[S] + (pol[S] - M) / np.linalg.norm(pol[S]-M)
Again full code & result below:
import matplotlib.pyplot as plt
import numpy as np
from scipy.spatial import ConvexHull
r = 10 # radius
center = [3, 3]
pol = polygon(7, r, 0, center)
pol2 = polygon(7, 1.2*r, 0, center) # for annotations
hull = ConvexHull(pol)
labels = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', "L", 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
fig = plt.figure(figsize=(4, 4), dpi=100)
for simplex in hull.simplices:
plt.plot(pol[simplex,0], pol[simplex,1], 'k-')
plt.plot(pol[:,0], pol[:,1], 'gs', ms=10)
if labels is not None:
for i, label in enumerate(labels):
if i <= len(pol)-1:
S = i
(N_1, N_2) = hull.neighbors[S]
M = (pol[N_1] + pol[N_2]) / 2
M_ext = pol[S] + (pol[S] - M) / np.linalg.norm(pol[S] - M) * 0.2*r
plt.annotate(label, xy=M_ext, xytext=(0, 0),
textcoords='offset points', ha="center", va="center")
plt.xlim(center[0] - 1.5*r, center[0] + 1.5*r)
plt.ylim(center[1] - 1.5*r, center[1] + 1.5*r)
plt.axis('off')
plt.show()