How to plot each pandas row as a line plot

Viewed 2418

I have a pandas dataframe where the column names are frequencies in 1 Hz steps, each row is a participant id, and the values are an amplitude^2 value for the participant in each respective frequency.

I am trying to plot a time-series of the data where the x axis are the frequencies, and the y axis is the amplitude^2 value, in "spaghetti plot" style, i.e. there is one line plotted for each row of my dataframe:

Here is a small snippet of my data:

data = [['1', 9.45e-09, 9.85e-09, 8.33e-09, 6.06e-09, 4.80e-09, 4.08e-09],
        ['2', 1.30e-08, 1.25e-08, 8.99e-09, 6.25e-09, 4.44e-09, 3.45e-09],
        ['3', 9.32e-09, 8.60e-09, 5.67e-09, 3.68e-09, 2.53e-09, 1.75e-09]]

fft_df = df = pd.DataFrame(data, columns = ['id', '1','2','3','4','5','6']).set_index('id')

# display(fft_df)
               1             2             3             4             5             6
id                                                                                    
1   9.450000e-09  9.850000e-09  8.330000e-09  6.060000e-09  4.800000e-09  4.080000e-09
2   1.300000e-08  1.250000e-08  8.990000e-09  6.250000e-09  4.440000e-09  3.450000e-09
3   9.320000e-09  8.600000e-09  5.670000e-09  3.680000e-09  2.530000e-09  1.750000e-09

Using matplotlib, if I use the fft_df column names as the x argument, and the fft_df column mean as the y argument, matplotlib will return a lineplot. However if I remove the .mean() from the y input it will return an error. I cannot seem to figure out how to plot one line for each row in fft_df:

plt.figure(figsize=(10, 10))
plt.ylabel('Absolute Power (log)',fontsize=12)
plt.xlabel('Frequencies',fontsize=12)
plt.plot(fft_df.columns,fft_df.mean())

enter image description here

3 Answers
  • As shown in another answer, it's not necessary to use pandas, however, the data is stated to already be in pandas, and using pandas makes it easier to plot, and to perform further analysis, such as extracting summary statistics. Most functions are vectorized, and numpy is a dependency.
    • df.T.describe() or df.describe()
  • Transpose the dataframe with .T
  • Plot with pandas.DataFrame.plot, which returns an axes
  • Tested in python 3.8.11, pandas 1.3.1 and matplotlib 3.4.2
import pandas as pd
import matplotlib.pyplot as plt

# create dataframe
data = [['1', 9.45e-09, 9.85e-09, 8.33e-09, 6.06e-09, 4.80e-09, 4.08e-09], ['2', 1.30e-08, 1.25e-08, 8.99e-09, 6.25e-09, 4.44e-09, 3.45e-09], ['3', 9.32e-09, 8.60e-09, 5.67e-09, 3.68e-09, 2.53e-09, 1.75e-09]]
df = pd.DataFrame(data, columns = ['id', '1', '2', '3', '4', '5', '6']).set_index('id')

# transpose and plot
ax = df.T.plot(figsize=(7, 6))
ax.set_ylabel('Absolute Power (log)', fontsize=12)
ax.set_xlabel('Frequencies', fontsize=12)
plt.show()

enter image description here

I think, the easiest solution would be to transpose your DataFrame and then use pandas' plotting method. This is somewhat based on this answer. The code would look like this:

import pandas as pd
import matplotlib.pyplot as plt

data = [['1', 9.45e-09, 9.85e-09, 8.33e-09, 6.06e-09, 4.80e-09, 4.08e-09],
        ['2', 1.30e-08, 1.25e-08, 8.99e-09, 6.25e-09, 4.44e-09, 3.45e-09],
        ['3', 9.32e-09, 8.60e-09, 5.67e-09, 3.68e-09, 2.53e-09, 1.75e-09]]

df = pd.DataFrame(data, columns = ['id', '1','2','3','4','5','6']).set_index('id')

# create figure and axis
fig, ax = plt.subplots(figsize=(10, 10))

# setting the axis' labels
ax.set_ylabel('Absolute Power (log)',fontsize=12)
ax.set_xlabel('Frequencies',fontsize=12)

# transposing (switchung rows and columns) of DataFrame df and
# plot a line for each column on the axis ax, which was created previously
df.T.plot(ax=ax)

The result looks like this: plot

You don't have to use pandas at all.

Besides, if the nature of your data is continuous, and you are going to have a lot of records, I don't recommend working with pandas as it might be inefficient for some tasks. There are much more suitable libraries for that, such as numpy and scipy. Both libraries allow you to compute simple statistics alongside complex ones.

data = [[9.45e-09, 9.85e-09, 8.33e-09, 6.06e-09, 4.80e-09, 4.08e-09],
        [1.30e-08, 1.25e-08, 8.99e-09, 6.25e-09, 4.44e-09, 3.45e-09],
        [9.32e-09, 8.60e-09, 5.67e-09, 3.68e-09, 2.53e-09, 1.75e-09]]


plt.figure(figsize=(10, 10))
plt.ylabel('Absolute Power (log)',fontsize=12)
plt.xlabel('Frequencies',fontsize=12)

x = list(range(1, len(data[0]) +1))
for i in range(len(data)):
    plt.plot(x, data[i], label=str(i))

plt.show()

enter image description here

Related