Search code examples
pandasdataframedictionarymatplotlibtime-series

How can I plot multiple graphs on one plot, using a dictionary to contain the filename with the x and y values for each graph?


I'm creating a function that takes 3 inputs. 1 is a list of file names and 2 and 3 are the headers of the columns for 'TIME' and 'X' Values within each file. . The function will plot the Time vs X values for that file and then iterate onto the next file and do the same, resulting in multiple graphs on one plot, with each graph coming from a different dataset/ file.

My problem is that every time Python iterates through a file, it will then plot that file's data instead of the previous file, rather than all together on one plot. To solve this I tried a method using dictionaries, iterating through the files and storing the Time and X values, then, once every file has been iterated through, the Time and X values can all be plotted in one sweep.

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import pickle
from datetime import datetime
from scipy.fft import rfft, rfftfreq
import scipy
from scipy.fft import irfft
from scipy import signal

def func(x):
    s1 = x%100
    s2 = (x//100)%100
    s3 = x//10000
    return s3*3600 + s2*60 + s1


#Defining function for use on time series. An equal length array of times, 'TIME', and values, 'X', is required.

def Fourier(TimeSeriesHeading = [], ValuesHeading = [], FileNames = [],  X_Axis_Label = None, Y_Axis_Label = None, Title = None, Legend_Title = None):
    my_dict = {"Time":[],"Value":[],"File":[]}
    for k in FileNames:
                data = pd.read_csv(k, sep =" ")
                my_dict["File"].append(k)
                #DAWN_time_data_ESKI_11_21 = time_data_ESKI_11_21[212:513]
                #DAWN_X_amplitude_ESKI_11_21 = X_amplitude_ESKI_11_21[212:513]
    for i in TimeSeriesHeading:
               
                    time_data_1 = (data[i].map(func))

                    my_dict["Time"].append(time_data_1)

    for j in ValuesHeading:
        
                    values_data_1 = data[j]

                    my_dict["Value"].append(values_data_1)


    plt.plot((my_dict["Time"]), (my_dict["Value"]))
    plt.xlabel(X_Axis_Label)
    plt.ylabel(Y_Axis_Label)
    plt.title(Title)
    
    if Legend_Title == Legend_Title:
            plt.legend(title = Legend_Title, loc=(1.04, 0))
    return

Then I'm calling the function such as:

Fourier(['TIME','TIME'], ['X','X'], ["PINA  50.199 263.960 20011121 GEODETIC nT17280","ISLL  53.856 265.340 20011121 GEODETIC nT17280"])

^^^Inputting the header for the Time values, the X values and the file names containing aforementioned headers.

I've attached the output plot of the code below. I expected to see 2 different graphs on 1 plot for my 2 different datasets. However, as you can tell from the plot, there's no actual graph.

output

My data is in the format, see the 'TIME' and 'X' columns: Data Data2

Is there a more simple alternative to creating a function that can iterate through a list containing any number of files, producing plots based on the columns within those files?


Solution

  • If I understood correctly you want all the graphs on the same plot. Try the code below. It makes a figure each time the Fourier function is called. During each call, it'll plot graphs on the same axes.

    def Fourier(TimeSeriesHeading=[], ValuesHeading=[], FileNames=[], X_Axis_Label=None,
                Y_Axis_Label=None, Title=None, Legend_Title=None):
        fig, ax = plt.subplots(figsize=(8, 3))
        ax.set_title(Title)
        
        for ts_heading in TimeSeriesHeading:
            for vals_heading in ValuesHeading:
                for filename in FileNames:
                    #Read the data for this (timeseries, value heading, filename) combo
                    data = pd.read_csv(filename, sep=' ')
                    time_data_1 = data[ts_heading].map(func)
                    values_data_1 = data[vals_heading]
                    
                    #Overlay onto the existing plot
                    ax.plot(time_data_1, values_data_1,
                            label=f'{ts_heading}/{vals_heading}/{filename}')
    
        #Add legend after all graphs drawn
        ax.legend(title=Legend_Title, loc='best')