简体   繁体   中英

How to identify graph lines in matplotlib

I have x, y data for paths in the following format (sample only for illustration):

   seq    p1      p2
0  20      2      3
1  20      2      4
2  20      4      4
3  22      5      5
4  22      5      6
5  23      6      2
6  23      6      3
7  23      6      4

Each path has number of points and they are identified by a seq, points belonging to same seq is considered to be one path and so on..

I have plotted these paths(using my real data which is in same format as above)using the following code and also have attached the result:

import matplotlib.pyplot as plt

fig, ax = plt.subplots(figsize=(12, 8))

for (key, grp) in df.groupby("seq"):
    grp.plot(linestyle = "solid", x="p1", y="p2", ax = ax, label = key)

box = ax.get_position()
ax.set_position([box.x0, box.y0, box.width * 0.8, box.height])
ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))

plt.title("Paths")
plt.show()

I have plotted some 40 paths, now the problem is how should I identify that which path is for uid 184, or which one is uid-194 ? They both are labelled with same color in the legend. Is there a way that I am able to identify each path distinctively, maybe labelling somewhere on the path(but that might make the graph cluttered).

My second question is I want to mark the starting and ending points of each path/ trajectory. Like start-point can be green and the end-point can be red . For example in the above sample df, for uid-20 the starting points are (2,3) in row 0 and end-points are (4,4) in row 2. Please suggest a way to mark these starting and ending points for each path in the df.

I am not sure how much this answers your question, but this is a way to make the line colors compliant with a colormap, which usually helps me visualize different lines and their trends easier, but might not be very convenient to single out a single line.

cmap = plt.cm.get_cmap('viridis')
groups = df.groupby("uid")
ngroups = len(groups)

for i, (key, grp) in enumerate(groups):
    grp.plot(linestyle="solid", x="px", y="py", ax=ax, label=key, color=cmap(i/(ngroups-1))

to add markers for the first and last points, just single them out and assign them the color and marker you like. So, rewriting the for loop above:

for i, (key, grp) in enumerate(df.groupby("uid")):
    grp.plot(linestyle="solid", x="px", y="py", ax=ax, label=key, color=cmap(i/(ngroups-1)))
    grp.iloc[[0]].plot(marker="o", x="px", y="py", ax=ax, color='r', legend=False)
    grp.iloc[[-1]].plot(marker="o", x="px", y="py", ax=ax, color='g', legend=False)

if you want each marker to have a different tone of red and green, you can use the Reds and Greens colormaps such as:

start_cmap =  plt.cm.get_cmap('Reds')
end_cmap =  plt.cm.get_cmap('Greens')

and in the loop it will be

grp.iloc[[0]].plot(marker="o", x="px", y="py", ax=ax, color=start_cmap(i/(ngroups-1)), legend=False)
grp.iloc[[-1]].plot(marker="o", x="px", y="py", ax=ax, color=end_cmap(i/(ngroups-1)), legend=False)

EDITS

Handling Legends

To plot only the lines and not the end points markers, we use the fact that we have first plotted the line and then the two markers, and this is how the plots are pushed into the axis line queue, so we skip over the markers and explicitly tell the legend which lines to consider:

ax.legend(ax.lines[::3], groups.groups.keys(), loc='center left', bbox_to_anchor=(1, 0.5))

Using Colorbar

If using a colormap for the lines, it is useful to display a colorbar rather than legend, so we use something like this:

from matplotlib.colorbar import ColorbarBase
import matplotlib as mp

values = list(groups.groups.keys())
cax = fig.add_axes([0.92, 0.12, 0.02, 0.75])
cbar = ColorbarBase(cax, cmap=cmap, format='%d', ticks=values, drawedges=False, norm=mp.colors.Normalize(vmin=min(values), vmax=max(values)))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM