I have text files named as 5.txt, 10.txt, 15.txt, 20.txt but when I read the files with glob module and use fname variable in the legend I get disorganized legend data.
for fname in glob("*.txt"):
potential, current_density = np.genfromtxt(fname, unpack=True)
current_density = current_density*1e6
ax = plt.gca()
ax.get_yaxis().get_major_formatter().set_useOffset(False)
plt.plot(potential,current_density, label=fname[0:-4])
plt.legend(loc=4,prop={'size':12},
ncol=1, shadow=True, fancybox=True,
title = "Scan rate (mV/s)")
How can I plot and give the corresponding label to the data with in increasing order?
Just to provide yet another method, which does not require to change anything in the plotting part of the script:
handles, labels = plt.gca().get_legend_handles_labels()
handles, labels = zip(*[ (handles[i], labels[i]) for i in sorted(range(len(handles)), key=lambda k: list(map(int,labels))[k])] )
plt.legend(handles, labels, loc=4, ...)
Method 1 (Recommended)
You will need to sort and display the legend yourself. plt.legend
takes a list of lines and a list of strings as the first two optional positional arguments. You can maintain a list of the items you need, sort it into the order you want, and pass the portions you want over to legend
.
ax = plt.gca() legend_items = [] for fname in glob("*.txt"): potential, current_density = np.genfromtxt(fname, unpack=True) current_density *= 1e6 line, = ax.plot(potential, current_density) name = fname[0:-4] legend_items.append((int(name), line, name)) legend_items.sort() ax.get_yaxis().get_major_formatter().set_useOffset(False) ax.legend([x[1] for x in legend_items], [x[2] for x in legend_items], loc=4, prop={'size':12}, ncol=1, shadow=True, fancybox=True, title = "Scan rate (mV/s)")
Major additions are marked in bold, while minor style changes that can probably be ignored are marked in italics.
Major additions include the accumulation of the items for the legend. I use tuples for each item because a list of tuples is automatically sorted by the first element first. The comma in line, = ax.plot...
is necessary because it triggers argument unpacking on the list that plot
returns. An alternative would be to do line = ax.plot(...)[0]
. The file name is no longer added as an explicit label to the data.
Among the minor changes, I switched to using ax.plot
and ax.legend
instead of plt.plot
and plt.legend
. This is the object oriented part of Matplotlib's API and it makes things a little clearer. Also, you don't have to keep calling gca()
to get the reference over and over this way. Also, set_useoffset
only needs to be called only once, not inside the loop.
Method 2
Another way to approach the problem would be to pre-sort the file names before processing them, so that they appear in the correct order in your legend:
import os
file_list = os.listdir('.')
file_list = [x for x in file_list if x.endswith('.txt')]
file_list.sort(key=lambda x: int(x[0:-4]))
for fname in file_list:
...
You will have to do the name filtering yourself, but it is not especially difficult. The sorting key is just the number. Also, you will note that I got tired of doing the custom fancy formatting for this update :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With