9

I've been trying for weeks to plot 3 sets of (x, y) data on the same plot from a .CSV file, and I'm getting nowhere. My data was originally an Excel file which I have converted to a .CSV file and have usedpandas to read it into IPython as per the following code:

from pandas import DataFrame, read_csvimport pandas as pd# define data locationdf = read_csv(Location)df[['LimMag1.3', 'ExpTime1.3', 'LimMag2.0', 'ExpTime2.0', 'LimMag2.5','ExpTime2.5']][:7]

My data is in the following format:

Type    mag1    time1   mag2    time2   mag3    time3M0      8.87    41.11   8.41    41.11   8.16    65.78;...M6     13.95  4392.03  14.41 10395.13  14.66 25988.32

I'm trying to plottime1 vsmag1,time2 vsmag2 andtime3 vsmag3, all on the same plot, but instead I get plots oftime.. vsType, eg. for the code:

df['ExpTime1.3'].plot()

I get'ExpTime1.3' (y-axis) plotted againstM0 toM6 (x-axis), when what I want is'ExpTime1.3' vs'LimMag1.3', with x-labelsM0 -M6.

  1. How do I get'ExpTime..' vs'LimMag..' plots, with all 3 sets of data on the same plot?

  2. How do I get theM0 -M6 labels on the x-axis for the'LimMag..' values (also on the x-axis)?

Since trying askewchan's solutions, which did not return any plots for reasons unknown, I've found that I can get a plot ofExpTimevsLimMagusingdf['ExpTime1.3'].plot(),if I change the dataframe index (df.index) to the values of the x axis (LimMag1.3). However, this appears to mean that I have to convert each desired x-axis to the dataframe index by manually inputing all the values of the desired x-axis to make it the data index. I have an awful lot of data, and this method is just too slow, and I can only plot one set of data at a time, when I need to plot all 3 series for each dataset on the one graph. Is there a way around this problem? Or can someone offer a reason, and a solution, as to why I I got no plots whatsoever with the solutions offered by askewchan?\

In response to nordev, I have tried the first version again, bu no plots are produced, not even an empty figure. Each time I put in one of theax.plotcommands, I do get an output of the type:[<matplotlib.lines.Line2D at 0xb5187b8>], but when I enter the commandplt.show()nothing happens.When I enterplt.show()after the loop in askewchan's second solution, I get an error back sayingAttributeError: 'function' object has no attribute 'show'

I have done a bit more fiddling with my original code and can now get a plot ofExpTime1.3vsLimMag1.3 with the codedf['ExpTime1.3'][:7].plot(),by making the index the same as the x axis (LimMag1.3), but I can't get the other two sets of data on the same plot. I would appreciate any further suggestions you may have. I'm using ipython 0.11.0 via Anaconda 1.5.0 (64bit) and spyder on Windows 7 (64bit), python version is 2.7.4.

askedMay 15, 2013 at 15:19
user2324693's user avatar
7
  • Just a thought; havingM0 -M6 as labels on the x-axis would have no real meaning in this situation, as there arethree differentLimMag..-values for everyM..-label, meaning that every label would have to be placed three different places on the axis. This will ultimately look very confusing rather than informative.CommentedMay 16, 2013 at 7:52
  • What isplt defined as? It shouldn't be a'function' object Are you familiar with using matplotlib and pyplot?CommentedMay 16, 2013 at 15:17
  • Hi askewchan, in answer to your question, I'm totally unfamiliar with matplotlib, pylab, python; in fact I've never done any sort of programming or used anything other than excel - hence the struggle..CommentedMay 16, 2013 at 15:36
  • @user2324693 Try looking here to get started with plotting:matplotlib.org/users/pyplot_tutorial.htmlCommentedMay 16, 2013 at 16:31
  • Hi nordev, the solution with the log x-axis is probably the best, minus the end labels, as they're not correct, ie M0 is not the lowest valued spectral class. However, when I try to run it, I get an error message with respect to the range as 'expecting integer, but got float'. The data are decimals, but I don't know how to fix this so it will expect float, as I don't understand your code.CommentedJun 7, 2013 at 14:15

2 Answers2

12

If I have understood you correctly, both from this question as well as yourprevious one on the same subject, the following should be basic solutions you could customize to your needs.

Several subplots:

Note that this solution will output as many subplots as there are Spectral classes (M0, M1, ...) vertically on the same figure. If you wish tosave the plot of each Spectral class in a separate figure, the code needs some modifications.

import pandas as pdfrom pandas import DataFrame, read_csvimport numpy as npimport matplotlib.pyplot as plt# Here you put your code to read the CSV-file into a DataFrame dfplt.figure(figsize=(7,5)) # Set the size of your figure, customize for more subplotsfor i in range(len(df)):    xs = np.array(df[df.columns[0::2]])[i] # Use values from odd numbered columns as x-values    ys = np.array(df[df.columns[1::2]])[i] # Use values from even numbered columns as y-values    plt.subplot(len(df), 1, i+1)    plt.plot(xs, ys, marker='o') # Plot circle markers with a line connecting the points    for j in range(len(xs)):        plt.annotate(df.columns[0::2][j][-3:] + '"', # Annotate every plotted point with last three characters of the column-label                     xy = (xs[j],ys[j]),                     xytext = (0, 5),                     textcoords = 'offset points',                     va = 'bottom',                     ha = 'center',                     clip_on = True)    plt.title('Spectral class ' + df.index[i])    plt.xlabel('Limiting Magnitude')    plt.ylabel('Exposure Time')    plt.grid(alpha=0.4)plt.tight_layout()plt.show()

enter image description here

All in same Axes, grouped by rows (M0, M1, ...)

Here is another solution to get all the different Spectral classes plotted in the same Axes with a legend identifying the different classes. Theplt.yscale('log') is optional, but seeing as how the values span such a great range, it is recommended.

import pandas as pdfrom pandas import DataFrame, read_csvimport numpy as npimport matplotlib.pyplot as plt# Here you put your code to read the CSV-file into a DataFrame dffor i in range(len(df)):    xs = np.array(df[df.columns[0::2]])[i] # Use values from odd numbered columns as x-values    ys = np.array(df[df.columns[1::2]])[i] # Use values from even numbered columns as y-values    plt.plot(xs, ys, marker='o', label=df.index[i])    for j in range(len(xs)):        plt.annotate(df.columns[0::2][j][-3:] + '"', # Annotate every plotted point with last three characters of the column-label                     xy = (xs[j],ys[j]),                     xytext = (0, 6),                     textcoords = 'offset points',                     va = 'bottom',                     ha = 'center',                     rotation = 90,                     clip_on = True)plt.title('Spectral classes')plt.xlabel('Limiting Magnitude')plt.ylabel('Exposure Time')plt.grid(alpha=0.4)    plt.yscale('log')plt.legend(loc='best', title='Spectral classes')plt.show()

enter image description here

All in same Axes, grouped by columns (1.3", 2.0", 2.5")

A third solution is as shown below, where the data are grouped by the series (columns 1.3", 2.0", 2.5") rather than by the Spectral class (M0, M1, ...). This example is very similar to @askewchan's solution. One difference is that the y-axis here is a logarithmic axis, making the lines pretty much parallel.

import pandas as pdfrom pandas import DataFrame, read_csvimport numpy as npimport matplotlib.pyplot as plt# Here you put your code to read the CSV-file into a DataFrame dfxs = np.array(df[df.columns[0::2]]) # Use values from odd numbered columns as x-valuesys = np.array(df[df.columns[1::2]]) # Use values from even numbered columns as y-valuesfor i in range(df.shape[1]/2):     plt.plot(xs[:,i], ys[:,i], marker='o', label=df.columns[0::2][i][-3:]+'"')     for j in range(len(xs[:,i])):        plt.annotate(df.index[j], # Annotate every plotted point with its Spectral class                     xy = (xs[:,i][j],ys[:,i][j]),                     xytext = (0, -6),                     textcoords = 'offset points',                     va = 'top',                     ha = 'center',                     clip_on = True)plt.title('Spectral classes')plt.xlabel('Limiting Magnitude')plt.ylabel('Exposure Time')plt.grid(alpha=0.4)    plt.yscale('log')plt.legend(loc='best', title='Series')plt.show()

enter image description here

answeredMay 16, 2013 at 8:57
sodd's user avatar
Sign up to request clarification or add additional context in comments.

19 Comments

Hi nordev, I've just seen the above, thanks, I'll give it a go. I was hoping to be able to have them all on one plot, as I have 6 similar plots to do, all with 3 individual series (1.3", 2.0", and 2.5"). It's going to be an awful of of graphs if I have to do each spectral class independently! My first attempt was in Excel, it sort of did what I want, but only in a 3D plot, and it wasn'r very informative - hence the switch to matplotlib...
Hi nordev, thanks so much for all your hard work, it's really appreciated :) Hopefully I'll be able to work through this and get some useful graphs - very much a beginner here, up until two weeks ago I'd never done any type of programming before; talk about being thrown in at the deep end! lol :)
Hi nordev, as indicated above, this third option is the one I'd like to use, but without the M labels. Omitting the 'j' loop, I obtain a linear plot with the 'i' loop. However, when I run 'plt.title', I lose my plot and am left with an empty box. Running the rest of the code results in the error message: C:\Anaconda\lib\site-packages\matplotlib\axes.py:4601: UserWarning: No labeled objects found. Use label='...' kwarg on individual plots.warnings.warn("No labeled objects found. ", and a nicely formatted grid with no data in it, despite having data in a linear plot after the 'i' loop ran.
Another question: How do I limit the number of rows to be plotted? I only want to go from M0 - M6. The full data as displayed after the 'i' loop goes to M9.
Re the comment re ending up with no data in my graph, I think the problem may have something to do with the (label=df.columns[0::2][i][-3]+'"') code, as I don't get the 'no labeled objects found' error if I omit it, but I still end up with no data once I input the title and x,y labels, or change the y axis to log. I have no idea what the problem might be, however, or how to fix it.
|
3

You can callpyplot.plot(time, mag) three different times in the same figure. It would be wise to give a label to them. Something like this:

import matplotlib.pyplot as plt...fig = plt.figure()ax = fig.add_subplot(111)ax.plot(df['LimMag1.3'], df['ExpTime1.3'], label="1.3")ax.plot(df['LimMag2.0'], df['ExpTime2.0'], label="2.0")ax.plot(df['LimMag2.5'], df['ExpTime2.5'], label="2.5")plt.show()

If you want to loop it, this would work:

fig = plt.figure()ax = fig.add_subplot(111)for x,y in [['LimMag1.3', 'ExpTime1.3'],['LimMag2.0', 'ExpTime2.0'], ['LimMag2.5','ExpTime2.5']]:    ax.plot(df[x], df[y], label=y)plt.show()
answeredMay 15, 2013 at 15:48
askewchan's user avatar

13 Comments

Hi askewchan, Thanks very much for the help, but there still seems to be a problem. I've run both of the codes you've provided, and even though no errors are being returned, no plots are being displayed. Is there a line of code missing, ie is there some code that should come between the ax.plot commands and the plt.show() commands? I get the distinct impression that ipython is waiting for some other input, but I have zero idea of what that might be..
@user2324693 Given that your DataFramedf is formatted correctly, then @askewchan's code should be working perfectly. At least I have no problem creating the plots from his code (pandas 0.11.0 & matplotlib 1.2.1).
@askewchan Your plots are "reversed" in the sense that'ExpTime..' should be on the y-axis, and'LimMag..' on the x-axis.
@user2324693 I'm not sure what would cause that. As nordev seems to be able to get it to work, I don't know how to reproduce the problem (I don't have pandas).
Thanks @nordev, I am used to time being on the x-axis :P
|

Your Answer

Sign up orlog in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

By clicking “Post Your Answer”, you agree to ourterms of service and acknowledge you have read ourprivacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.