Matplotlib: Import and plot multiple time series w

2019-07-20 10:43发布

问题:

I have several spreadsheets containing data saved as comma delimited (.csv) files in the following format: The first row contains column labels as strings ('Time', 'Parameter_1'...). The first column of data is Time and each subsequent column contains the corresponding parameter data, as a float or integer.

I want to plot each parameter against Time on the same plot, with parameter legends which are derived directly from the first row of the .csv file.

My spreadsheets have different numbers of (columns of) parameters to be plotted against Time; so I'd like to find a generic solution which will also derive the number of columns directly from the .csv file.

The attached minimal working example shows what I'm trying to achieve using np.loadtxt (minus the legend); but I can't find a way to import the column labels from the .csv file to make the legends using this approach.

np.genfromtext offers more functionality, but I'm not familiar with this and am struggling to find a way of using it to do the above.

Plotting data in this style from .csv files must be a common problem, but I've been unable to find a solution on the web. I'd be very grateful for your help & suggestions.

Many thanks

"""
Example data: Data.csv:
Time,Parameter_1,Parameter_2,Parameter_3
0,10,0,10
1,20,30,10
2,40,20,20
3,20,10,30  
"""
import numpy as np
import matplotlib.pyplot as plt

data = np.loadtxt('Data.csv', skiprows=1, delimiter=',') # skip the column labels
cols = data.shape[1] # get the number of columns in the array
for n in range (1,cols):
    plt.plot(data[:,0],data[:,n]) # plot each parameter against time
plt.xlabel('Time',fontsize=14)
plt.ylabel('Parameter values',fontsize=14)
plt.show()

回答1:

The function numpy.genfromtxt is more for broken tables with missing values rather than what you're trying to do. What you can do is simply open the file before handing it to numpy.loadtxt and read the first line. Then you don't even need to skip it. Here is an edited version of what you have here above that reads the labels and makes the legend:

"""
Example data: Data.csv:
Time,Parameter_1,Parameter_2,Parameter_3
0,10,0,10
1,20,30,10
2,40,20,20
3,20,10,30  
"""
import numpy as np
import matplotlib.pyplot as plt

#open the file
with open('Data.csv') as f:
    #read the names of the colums first
    names = f.readline().strip().split(',')
    #np.loadtxt can also handle already open files
    data = np.loadtxt(f, delimiter=',') # no skip needed anymore

cols = data.shape[1]
for n in range (1,cols):
    #labels go in here
    plt.plot(data[:,0],data[:,n],label=names[n])

plt.xlabel('Time',fontsize=14)
plt.ylabel('Parameter values',fontsize=14)

#And finally the legend is made
plt.legend()
plt.show()


回答2:

Here's my minimal working example for the above using genfromtxt rather than loadtxt, in case it is helpful for anyone else. I'm sure there are more concise and elegant ways of doing this (I'm always happy to get constructive criticism on how to improve my coding), but it makes sense and works OK:

import numpy as np
import matplotlib.pyplot as plt

arr = np.genfromtxt('Data.csv', delimiter=',', dtype=None) # dtype=None automatically defines appropriate format (e.g. string, int, etc.) based on cell contents
names = (arr[0])  # select the first row of data = column names
for n in range (1,len(names)):  # plot each column in turn against column 0 (= time)
    plt.plot (arr[1:,0],arr[1:,n],label=names[n]) # omitting the first row ( = column names)
plt.legend()    
plt.show()