How to annotated labels to a 3D matplotlib scatter plot? - python-3.x

I have run a sklearn - Principal Component Analysis on my data with 3 principal components (PC1, PC2, PC3). The data looks like this (it's a pandas DataFrame):
Here is the code for plotting the principle components:
from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
%matplotlib
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.set_title('3D Scatter Plot')
ax.set_xlabel('PC1')
ax.set_ylabel('PC2')
ax.set_zlabel('PC3')
ax.view_init(elev=12, azim=40) # elevation and angle
ax.dist=10 # distance
ax.scatter(
data_df_3dx['PC1'], data_df_3dx['PC2'], data_df_3dx['PC3'], # data
#color='purple', # marker colour
#marker='o', # marker shape
s=60 # marker size
)
plt.show()
My problem, how do I add labels (like 'GER, medium') to the points? Hope someone can help me :)

In the following posts [1], [2] the plotting of 3D arrows in matplotlib is discussed.
Similarly Annotation3D class (inherited from Annotation) can be created:
from mpl_toolkits.mplot3d.proj3d import proj_transform
from matplotlib.text import Annotation
class Annotation3D(Annotation):
'''Annotate the point xyz with text s'''
def __init__(self, s, xyz, *args, **kwargs):
Annotation.__init__(self,s, xy=(0,0), *args, **kwargs)
self._verts3d = xyz
def draw(self, renderer):
xs3d, ys3d, zs3d = self._verts3d
xs, ys, zs = proj_transform(xs3d, ys3d, zs3d, renderer.M)
self.xy=(xs,ys)
Annotation.draw(self, renderer)
Further, we can define the annotate3D() function:
def annotate3D(ax, s, *args, **kwargs):
'''add anotation text s to to Axes3d ax'''
tag = Annotation3D(s, *args, **kwargs)
ax.add_artist(tag)
Using this function annotation tags can be added to Axes3d as in example bellow:
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import axes3d
from mpl_toolkits.mplot3d.art3d import Line3DCollection
# data: coordinates of nodes and links
xn = [1.1, 1.9, 0.1, 0.3, 1.6, 0.8, 2.3, 1.2, 1.7, 1.0, -0.7, 0.1, 0.1, -0.9, 0.1, -0.1, 2.1, 2.7, 2.6, 2.0]
yn = [-1.2, -2.0, -1.2, -0.7, -0.4, -2.2, -1.0, -1.3, -1.5, -2.1, -0.7, -0.3, 0.7, -0.0, -0.3, 0.7, 0.7, 0.3, 0.8, 1.2]
zn = [-1.6, -1.5, -1.3, -2.0, -2.4, -2.1, -1.8, -2.8, -0.5, -0.8, -0.4, -1.1, -1.8, -1.5, 0.1, -0.6, 0.2, -0.1, -0.8, -0.4]
group = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 2, 2, 2, 3, 3, 3, 3]
edges = [(1, 0), (2, 0), (3, 0), (3, 2), (4, 0), (5, 0), (6, 0), (7, 0), (8, 0), (9, 0), (11, 10), (11, 3), (11, 2), (11, 0), (12, 11), (13, 11), (14, 11), (15, 11), (17, 16), (18, 16), (18, 17), (19, 16), (19, 17), (19, 18)]
xyzn = zip(xn, yn, zn)
segments = [(xyzn[s], xyzn[t]) for s, t in edges]
# create figure
fig = plt.figure(dpi=60)
ax = fig.gca(projection='3d')
ax.set_axis_off()
# plot vertices
ax.scatter(xn,yn,zn, marker='o', c = group, s = 64)
# plot edges
edge_col = Line3DCollection(segments, lw=0.2)
ax.add_collection3d(edge_col)
# add vertices annotation.
for j, xyz_ in enumerate(xyzn):
annotate3D(ax, s=str(j), xyz=xyz_, fontsize=10, xytext=(-3,3),
textcoords='offset points', ha='right',va='bottom')
plt.show()

One way would be to plot each point individually inside of a for loop, that way you know the coordinates of each point and can add text to it.
for i in range(len(data_df_3dx)):
x, y, z = data_df_3dx.iloc[i]['PC1'], data_df_3dx.iloc[i]['PC2'], data_df_3dx.iloc[i]['PC3']
ax.scatter(x, y, z)
#now that you have the coordinates you can apply whatever text you need. I'm
#assuming you want the index, but you could also pass a column name if needed
ax.text(x, y, z, '{0}'.format(data_df_3dx.index[i]), size=5)

Related

How to improve cone - make the bases more like a circle?

I have a code for plotting a cone with some text and arrows like axes. How to change this code to get the bases of the cone looking like circles? Is the problem in the settings of margins? Or is it necessary to define circles in another way?
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits import mplot3d
from matplotlib.patches import FancyArrowPatch
from mpl_toolkits.mplot3d import proj3d
class Arrow3D(FancyArrowPatch):
def __init__(self, xs, ys, zs, *args, **kwargs):
FancyArrowPatch.__init__(self, (0, 0), (0, 0), *args, **kwargs)
self._verts3d = xs, ys, zs
def draw(self, renderer):
xs3d, ys3d, zs3d = self._verts3d
xs, ys, zs = proj3d.proj_transform(xs3d, ys3d, zs3d, renderer.M)
self.set_positions((xs[0], ys[0]), (xs[1], ys[1]))
FancyArrowPatch.draw(self, renderer)
nn = 400 # number of points along circle's perimeter
theta = np.linspace(0, 2*np.pi, nn)
rho = np.ones(nn)
# (x,y) represents points on circle's perimeter
x = np.ravel(rho*np.cos(theta))
y = np.ravel(rho*np.sin(theta))
fig, ax = plt.subplots()
plt.rcParams["figure.figsize"] = [5, 5]
figsize = (5, 5)
ax = plt.axes(projection='3d') # set the axes for 3D plot
ax.azim = -88 # y rotation (default=270)
ax.elev = 13 # x rotation (default=0)
# Low, high values of z for plotting 2 circles at different elevation
loz, hiz = -15, 15
# Plot two circles
ax.plot(x, y, hiz)
ax.plot(x, y, loz)
# Set some indices to get proper (x,y) for line plotting
lo1,hi1 = 15, 15+nn//2
lo2,hi2 = lo1+nn//2-27, hi1-nn//2-27
# Plot 3d lines using coordinates of selected points
ax.plot([x[lo1], x[hi1]], [y[lo1], y[hi1]], [loz, hiz])
ax.plot([x[lo2], x[hi2]], [y[lo2], y[hi2]], [loz, hiz])
eps = 0.005
ax.plot([0, 0], [0, 0], [0, 20]) # extend in z direction
ax.plot([0-eps, 0], [0-eps, -5], [0-eps, 0]) # extend in y direction
ax.plot([0, 1.3], [0, 0], [0, 0]) # extend in x direction
ax.plot([0+eps, 0.6], [0+eps, -4], [0+eps, 16]) # v vector
ax.plot([0.63, 0.63], [-4, -4], [16, -0.005]) # vertical projection
ax.plot([0+eps, 0.6], [0+eps, -4], [0+eps, -0.005]) # to the beginning
ax.scatter(0, 0, 20, marker=(3, 0, 0), s=100, clip_on=False)
ax.scatter(0, -5, 0, marker=(3, 0, 43), s=100, clip_on=False)
ax.scatter(1.3, 0, 0, marker=(3, 0, 30), s=100, clip_on=False)
ax.scatter(0.6, -4, 16, marker=(3, 0, 80), s=100, clip_on=False)
ax.scatter(0.6, -4, -0.005, marker=(3, 0, 0), s=100, clip_on=False)
a2 = Arrow3D([0.14, -0.515], [-5.581, 1.358], [14.73, 4.983], mutation_scale=20, arrowstyle="-|>", color="k", connectionstyle="arc3,rad=0.3")
ax.add_artist(a2)
ax.text3D(0.23, -5.23, 23.33, r'$A$')
ax.text3D(1.41, 1.29, -2.7, r'$B$')
ax.text3D(-0.31, 1.46, -12.6, r'$C$')
ax.text3D(0.4, -5.48, 17, r'$D$')
ax.text3D(0.64, 1.57, -9.95, r'$E$')
ax.text3D(-0.2, -5.5, 15.73, r'$F$')
# Hide axes
ax._axis3don = False
# Save the figure (.pdf)
margins = { # vvv margin in inches
"left" : 1 / figsize[0],
"bottom" : -2.45 / figsize[1],
"right" : 1 - 0.5 / figsize[0],
"top" : 1 + 1.8 / figsize[1]
}
fig.subplots_adjust(**margins)
plt.savefig('output.pdf')
plt.show()
From this code I got the following output:
The desired output is bases looking like a circle.
This is the view from above:
It is not a circle but an ellipse.
Desired shape of the cone:

Cannot save animation in python

import numpy as np
import pandas as pd
import matplotlib
# matplotlib.use("Agg")
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib.colors import cnames
from matplotlib import animation
t_start = 2 #start frame
t_end = 1711 #end frame
data = pd.read_csv('Sub6_cylinder0009_index_flex_processed.csv')
df = data.loc[t_start:t_end,'FT1X':'CMC5Z']
df_minmax = pd.DataFrame(index=list('xyz'),columns=range(2))
for i in list('xyz'):
c_max = df.max().max()
c_min = df.min().min()
df_minmax.loc[i] = np.array([c_min,c_max])
df_minmax = 3.3*df_minmax
df.columns = np.repeat(range(22),3)
N_tag = int(df.shape[1]/3) # nr of tags used (all)
N_trajectories = N_tag
t = np.linspace(0,data.Time[t_end],df.shape[0])
x_t = np.zeros(shape=(N_tag,df.shape[0],3))
for tag in range(22):
x_t[tag,:,:] = df[tag]
x_t = x_t[:, :, [0, 2, 1]]
fig = plt.figure()
ax = fig.add_axes([0, 0, 1, 1], projection='3d')
ax.axis('on')
#choose a different color for each trajectory
colors = plt.cm.jet(np.linspace(0, 1, N_trajectories))
# set up trajectory lines
lines = sum([ax.plot([], [], [], '-', c=c) for c in colors], [])
# set up points
pts = sum([ax.plot([], [], [], 'o', c=c) for c in colors], [])
#set up lines which create the stick figures
stick_defines = [
(0, 13),
(13, 14),
(14, 19),
(1, 5),
(2, 6),
(3, 7),
(4, 8),
(5, 9),
(6, 10),
(7, 11),
(8, 12),
(9, 15),
(10, 16),
(11, 17),
(12, 18),
(18, 21),
(15, 20)
]
stick_lines = [ax.plot([], [], [], 'k-')[0] for _ in stick_defines]
print(stick_lines)
ax.set_xlim3d([np.nanmin(x_t[:, :, 0]), np.nanmax(x_t[:, :, 0])])
ax.set_ylim3d([np.nanmin(x_t[:, :, 1])-400, np.nanmax(x_t[:, :, 1])+400])
ax.set_zlim3d([np.nanmin(x_t[:, :, 2]), np.nanmax(x_t[:, :, 2])])
ax.set_xlabel('X [mm]')
ax.set_ylabel('Y [mm]')
ax.set_zlabel('Z [mm]')
# set point-of-view: specified by (altitude degrees, azimuth degrees)
#ax.view_init(30, 25)
# initialization function: plot the background of each frame
def init():
for line, pt in zip(lines, pts):
line.set_data(np.array([]), np.array([]))
line.set_3d_properties(np.array([]))
pt.set_data(np.array([]),np.array([]))
pt.set_3d_properties(np.array([]))
return lines + pts
# animation function. This will be called sequentially with the frame number
def animate(i):
i = (5 * i) % x_t.shape[1]
for pt, xi in zip(pts, x_t):
x, y, z = xi[:i].T
pt.set_data(x[-1:], y[-1:])
pt.set_3d_properties(z[-1:])
for stick_line, (sp, ep) in zip(stick_lines, stick_defines):
stick_line._verts3d = x_t[[sp,ep], i, :].T.tolist()
#ax.view_init(30, 0.3 * i)
fig.canvas.draw()
return lines + pts + stick_lines
anim = animation.FuncAnimation(fig, animate, init_func=init,
frames=500, interval=30, blit=True, repeat=False)
# Save as mp4. This requires mplayer or ffmpeg to be installed
#anim.save('animation.mp4', progress_callback=lambda i, n: print(f'Saving frame {i} of {n}'))
plt.show()
anim.save('test.mp4', writer='ffmpeg')
This does not save animation. However,
anim.save('animation.mp4', progress_callback=lambda i, n: print(f'Saving frame {i} of {n}'))
Does save the animation but the rendering is not really sharp and quite blurry. How do I change that ?
The other points are:
How do I change all the scatter points to a single color ?eg dark grey or black
How do I change the index finger only to a different color? eg Index finger color red
best wishes,
PS: Attached is the animation
import numpy as np
import pandas as pd
import matplotlib
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib.colors import cnames
from matplotlib import animation
#=============================================================================================
t_start = 2# start frame
t_end = 1711# end frame
data = pd.read_csv('Sub6_cylinder0009_index_flex_processed.csv') # only coordinate data
df = data.loc[t_start:t_end,'FT1X':'CMC5Z']
# Find max and min values for animation ranges
df_minmax = pd.DataFrame(index=list('xyz'),columns=range(2))
for i in list('xyz'):
c_max = df.max().max()
c_min = df.min().min()
df_minmax.loc[i] = np.array([c_min,c_max])
df_minmax = 3.3*df_minmax # increase by 30% to make animation look better
df.columns = np.repeat(range(22),3) # store cols like this for simplicity
print(df.columns)
N_tag = int(df.shape[1]/3) # nr of tags used (all)
N_trajectories = N_tag
t = np.linspace(0,data.Time[t_end],df.shape[0]) # pseudo time-vector for first walking activity
x_t = np.zeros(shape=(N_tag,df.shape[0],3)) # empty animation array (3D)
for tag in range(22):
# # store data in numpy 3D array: (tag,time-stamp,xyz-coordinates)
x_t[tag,:,:] = df[tag]
x_t = x_t[:, :, [0, 2, 1]]
fig = plt.figure()
ax = fig.add_axes([0, 0, 1, 1], projection='3d')
ax.axis('on')
#choose a different color for each trajectory
#colors1 = plt.cm.Reds(np.linspace(0, 1, N_trajectories))
#colors2 = plt.cm.gray(np.linspace(0, 1, N_trajectories))
# set up trajectory lines
#lines = sum([ax.plot([], [], [], '-', c=c) for c in colors1], [])
# set up points
#pts = sum([ax.plot([], [], [], 'o--', c=c) for c in colors2], [])
#pts = ax.plot([], [], [], 'o', c=colors2[0])
#pts = ax.plot([], [], [], 'o-', c=colors2[8])
#set up lines which create the stick figures
stick_defines = [
(0, 13), # Thumb Tip
(13, 14),
(14, 19),
(1, 5), #Index Tip
(2, 6), # Middle Tip
(3, 7), # Ring Tip
(4, 8), # Pinky Tip
(5, 9),
(6, 10),
(7, 11),
(8, 12),
(9, 15),
(10, 16),
(11, 17),
(12, 18),
(18, 21),
(15, 20)
# (22, 23),
# (23, 24),
# (22, 26),
# (25,26)
]
stick_defines1 = [
# (0, 13), # Thumb Tip
# (13, 14),
# (14, 19),
(1, 5), #Index Tip
# (2, 6), # Middle Tip
# (3, 7), # Ring Tip
# (4, 8), # Pinky Tip
(5, 9),
# (6, 10),
# (7, 11),
# (8, 12),
(9, 15),
# (10, 16),
# (11, 17),
# (12, 18),
# (18, 21),
(15, 20)
# (22, 23),
# (23, 24),
# (22, 26),
# (25,26)
]
stick_lines = [ax.plot([], [], [], 'ko--', alpha=0.5)[0] for _ in stick_defines]
stick_lines1 = [ax.plot([], [], [], 'ro-')[0] for _ in stick_defines1]
print(stick_lines)
ax.set_xlim3d([np.nanmin(x_t[:, :, 0]), np.nanmax(x_t[:, :, 0])])
ax.set_ylim3d([np.nanmin(x_t[:, :, 1])-400, np.nanmax(x_t[:, :, 1])+400])
ax.set_zlim3d([np.nanmin(x_t[:, :, 2]), np.nanmax(x_t[:, :, 2])])
ax.set_xlabel('X [mm]')
ax.set_ylabel('Y [mm]')
ax.set_zlabel('Z [mm]')
# set point-of-view: specified by (altitude degrees, azimuth degrees)
#ax.view_init(30, 25)
# initialization function: plot the background of each frame
# def init():
# for pt in pts:#zip(pts):
# # line.set_data(np.array([]), np.array([]))
# # line.set_3d_properties(np.array([]))
# pt.set_data(np.array([]), np.array([]))
# pt.set_3d_properties(np.array([]))
# return pts
# animation function. This will be called sequentially with the frame number
def animate(i):
# we'll step two time-steps per frame. This leads to nice results.
i = (5 * i) % x_t.shape[1]
pts = []
for pt, xi in zip(pts, x_t):
x, y, z = xi[:i].T # note ordering of points to line up with true exogenous registration (x,z,y)
pt.set_data(x[-1:], y[-1:])
pt.set_3d_properties(z[-1:])
for stick_line, (sp, ep) in zip(stick_lines, stick_defines):
stick_line._verts3d = x_t[[sp,ep], i, :].T.tolist()
for stick_line1, (sp, ep) in zip(stick_lines1, stick_defines1):
stick_line1._verts3d = x_t[[sp,ep], i, :].T.tolist()
#ax.view_init(30, 0.3 * i)
fig.canvas.draw()
return pts + stick_lines+stick_lines1
# instantiate the animator.
anim = animation.FuncAnimation(fig, animate, frames=500, interval=30, blit=True, repeat=False)
plt.show()
# Save as mp4. This requires mplayer or ffmpeg to be installed
anim.save('animation.mp4', progress_callback=lambda i, n: print(f'Saving frame {i} of {n}'))
#anim.save('test.mp4', writer='ffmpeg')
I have managed to answer my questions, however, the saving of the animation still remains a problem, the current version works but the video is blurry and is not particularly sharp. The last line of code which is commented out simply does not work for unknown reasons.
If you have a better way to have save the animation with better resolution please let me know.
Attached is the animation.
best wishes,

Adding one colorbar for hist2d subplots and make them adjacent

I am struggling with tweaking a plot, I have been working on.
I am facing to two problems:
The plots should be adjacent and with 0 wspace and hspace. I set both values to zero but still there are some spaces between the plots.
I would like to have one colorbar for all the subplots (they all the same range). Right now, the code adds a colorbar to the last subplot as i understand that it needs the third return value of hist2D.
Here is my code so far:
def plot_panel(pannel_plot):
fig, ax = plt.subplots(3, 2, figsize=(7, 7), gridspec_kw={'hspace': 0.0, 'wspace': 0.0}, sharex=True, sharey=True)
fig.subplots_adjust(wspace=0.0)
ax = ax.flatten()
xmin = 0
ymin = 0
xmax = 0.19
ymax = 0.19
hist2_num = 0
h =[]
for i, j in zip(pannel_plot['x'].values(), pannel_plot['y'].values()):
h = ax[hist2_num].hist2d(i, j, bins=50, norm=LogNorm(vmin=1, vmax=5000), range=[[xmin, xmax], [ymin, ymax]])
ax[hist2_num].set_aspect('equal', 'box')
ax[hist2_num].tick_params(axis='both', top=False, bottom=True, left=True, right=False,
labelsize=10, direction='in')
ax[hist2_num].set_xticks(np.arange(xmin, xmax, 0.07))
ax[hist2_num].set_yticks(np.arange(ymin, ymax, 0.07))
hist2_num += 1
fig.colorbar(h[3], orientation='vertical', fraction=.1)
plt.show()
And the corrsiponding result:
Result
I would be glad for any heads up that i am missing!
You can use ImageGrid, which was designed to make this kind of things easier
data = np.vstack([
np.random.multivariate_normal([10, 10], [[3, 2], [2, 3]], size=100000),
np.random.multivariate_normal([30, 20], [[2, 3], [1, 3]], size=1000)
])
from mpl_toolkits.axes_grid1 import ImageGrid
fig = plt.figure(figsize=(4, 6))
grid = ImageGrid(fig, 111, # similar to subplot(111)
nrows_ncols=(3, 2), # creates 2x2 grid of axes
axes_pad=0.1, # pad between axes in inch.
cbar_mode="single",
cbar_location="right",
cbar_pad=0.1
)
for ax in grid:
h = ax.hist2d(data[:, 0], data[:, 1], bins=100)
fig.colorbar(h[3], cax=grid.cbar_axes[0], orientation='vertical')
or
data = np.vstack([
np.random.multivariate_normal([10, 10], [[3, 2], [2, 3]], size=100000),
np.random.multivariate_normal([30, 20], [[2, 3], [1, 3]], size=1000)
])
from mpl_toolkits.axes_grid1 import ImageGrid
fig = plt.figure(figsize=(4, 6))
grid = ImageGrid(fig, 111, # similar to subplot(111)
nrows_ncols=(3, 2), # creates 2x2 grid of axes
axes_pad=0.1, # pad between axes in inch.
cbar_mode="single",
cbar_location="top",
cbar_pad=0.1
)
for ax in grid:
h = ax.hist2d(data[:, 0], data[:, 1], bins=100)
fig.colorbar(h[3], cax=grid.cbar_axes[0], orientation='horizontal')
grid.cbar_axes[0].xaxis.set_ticks_position('top')

How to calculate the euclidean distance between neighbors in networkx using x,y coordinates automatically and find the minimum spanning tree

So far I calculate the euclidean distance between the neighbors manually. But I need help on our to calculate the distance automatically in the code. My code so far is:
import networkx as nx
import matplotlib.pyplot as plt
import seaborn as sns
sns.set()
G = nx.Graph()
list_edges = [(0,1,3.8), (0,2,3.6), (1,3,2.5), (2,4,3.5), (3,5,4.6), (3,6,4.0), (3,7,2.8), (4,8,2.9),
(4,9,2.7), (4,10,4.1), (7,8,2.2), (5,6,3.1), (6,7,3.2), (8,9,3.6), (9,10,3.4)]
G.add_weighted_edges_from(list_edges)
G.add_node(0, pos = (8.5,10.5))
G.add_node(1, pos = (5,9))
G.add_node(2, pos = (11.5,8.5))
G.add_node(3, pos = (5,6.5))
G.add_node(4, pos = (11.5,5))
G.add_node(5, pos = (1.5,3.5))
G.add_node(6, pos = (4.5,2.5))
G.add_node(7, pos = (7,4.5))
G.add_node(8, pos = (9,3.5))
G.add_node(9, pos = (12.5,2.5))
G.add_node(10, pos = (15.5,4))
T = nx.minimum_spanning_tree(G, algorithm='kruskal')
#print(G.adj.items())
#print(T.edges())
#node_list = G.nodes()
#print(node_list)
#print(nx.get_node_attributes(G,'pos'))
node_pos=nx.get_node_attributes(G,'pos')
edge_weight=nx.get_edge_attributes(G,'weight')
red_edges = T.edges()
node_col = ['white']
# If the edge is in the shortest path set it to red, else set it to white color
edge_col = ['black' if not edge in red_edges else 'red' for edge in G.edges()]
# Draw the nodes
nx.draw_networkx(G, node_pos,node_color= node_col, node_size=450)
# Draw the node labels
nx.draw_networkx_labels(G, node_pos,node_color= node_col)
# Draw the edges
nx.draw_networkx_edges(G, node_pos,edge_color= edge_col)
# Draw the edge labels
nx.draw_networkx_edge_labels(G, node_pos,edge_color= edge_col, edge_labels=edge_weight)
# Remove the axis
plt.axis('off')
# Show the plot
plt.show()
Any help will be appreciated
You are probably looking for scipy.spatial.distance.pdist, which calculates all pairwise distances. If you need only few distances, you could also calculate them with scipy.spatial.distane.euclidean.
The following code reproduces your results without the requirement of given distances:
import networkx as nx
import matplotlib.pyplot as plt
import numpy as np
from scipy.spatial.distance import pdist, squareform
import seaborn as sns
sns.set()
G = nx.Graph()
# list_edges = [(0, 1, 3.8), (0, 2, 3.6), (1, 3, 2.5), (2, 4, 3.5), (3, 5, 4.6), (3, 6, 4.0), (3, 7, 2.8), (4, 8, 2.9),
# (4, 9, 2.7), (4, 10, 4.1), (7, 8, 2.2), (5, 6, 3.1), (6, 7, 3.2), (8, 9, 3.6), (9, 10, 3.4)]
# G.add_weighted_edges_from(list_edges)
list_unweighted_edges = [(0, 1), (0, 2), (1, 3), (2, 4), (3, 5), (3, 6), (3, 7), (4, 8),
(4, 9), (4, 10), (7, 8), (5, 6), (6, 7), (8, 9), (9, 10)]
G.add_node(0, pos=(8.5, 10.5))
G.add_node(1, pos=(5, 9))
G.add_node(2, pos=(11.5, 8.5))
G.add_node(3, pos=(5, 6.5))
G.add_node(4, pos=(11.5, 5))
G.add_node(5, pos=(1.5, 3.5))
G.add_node(6, pos=(4.5, 2.5))
G.add_node(7, pos=(7, 4.5))
G.add_node(8, pos=(9, 3.5))
G.add_node(9, pos=(12.5, 2.5))
G.add_node(10, pos=(15.5, 4))
position_array = []
for node in sorted(G):
position_array.append(G.nodes[node]["pos"])
print(position_array)
distances = squareform(pdist(np.array(position_array)))
for u, v in list_unweighted_edges:
G.add_edge(u, v, weight=np.round(distances[u][v],decimals=1))
T = nx.minimum_spanning_tree(G, algorithm='kruskal')
node_pos = nx.get_node_attributes(G, 'pos')
edge_weight = nx.get_edge_attributes(G, 'weight')
red_edges = T.edges()
node_col = ['white']
# If the edge is in the shortest path set it to red, else set it to white color
edge_col = ['black' if not edge in red_edges else 'red' for edge in G.edges()]
# Draw the nodes
nx.draw_networkx(G, node_pos, node_color=node_col, node_size=450)
# Draw the node labels
nx.draw_networkx_labels(G, node_pos, node_color=node_col)
# Draw the edges
nx.draw_networkx_edges(G, node_pos, edge_color=edge_col)
# Draw the edge labels
nx.draw_networkx_edge_labels(G, node_pos, edge_color=edge_col, edge_labels=edge_weight)
# Remove the axis
plt.axis('off')
# Show the plot
plt.show()

Matplotlib not showing point in PyCharm

Using Python 3 in PyCharm on Windows 10
I have a list of tuples that I need to plot. But the matplotlib is showing an empty graph:
import matplotlib as mpl
import matplotlib.pyplot as plt
mpl.use('TkAgg')
input = [(1, 6), (4, 15), (7, 7), (10, 13), (11, 6),
(11, 18), (11, 21), (12, 10), (15, 18),
(16, 6), (18, 3), (18, 12), (19, 15), (22, 19)]
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
input_points = []
for array_x, array_y in input:
input_points.append(Point(array_x, array_y))
plt.plot(array_x, array_y)
plt.show()
How to get the points to show up and plotted in the graph?
To draw lines, plt.plot needs a list (or numpy array) of x-positions and a list of y-positions. The documentation lists the different options to draw markers and/or lines.
List comprehension is a handy way to extract x or y positions from a list of xy-coordinates.
import matplotlib.pyplot as plt
input_points = [(1, 6), (4, 15), (7, 7), (10, 13), (11, 6),
(11, 18), (11, 21), (12, 10), (15, 18),
(16, 6), (18, 3), (18, 12), (19, 15), (22, 19)]
array_x = [x for x, y in input_points]
array_y = [y for x, y in input_points]
plt.plot(array_x, array_y, marker='o', color='crimson', linestyle='-')
plt.show()

Resources