Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Changing the order of pandas/matplotlib line plotting without changing data order

Given the following example:

df = pd.DataFrame(np.random.randint(1,10, size=(8,3)), columns=list('XYZ'))
df.plot(linewidth=10)

The order of plotting puts the last column on top:

enter image description here

How can I make this keep the data & legend order but change the behaviour so that it plots X on top of Y on top of Z?

(I know I can change the data column order and edit the legend order but I am hoping for a simpler easier method leaving the data as is)

UPDATE: final solution used:

(Thanks to r-beginners) I used the get_lines to modify the z-order of each plot

df = pd.DataFrame(np.random.randint(1,10, size=(8,3)), columns=list('XYZ'))
fig = plt.figure()
ax = fig.add_subplot(111)
df.plot(ax=ax, linewidth=10)
lines = ax.get_lines()
for i, line in enumerate(lines, -len(lines)):
    line.set_zorder(abs(i))
fig

In a notebook produces:

enter image description here

like image 549
mrkbutty Avatar asked Oct 15 '25 08:10

mrkbutty


2 Answers

Get the default zorder and sort it in the desired order.


import matplotlib.pyplot as plt
import pandas as pd
import numpy as np
np.random.seed(2021)

df = pd.DataFrame(np.random.randint(1,10, size=(8,3)), columns=list('XYZ'))
ax = df.plot(linewidth=10)
l = ax.get_children()
print(l)
l[0].set_zorder(3)
l[1].set_zorder(1)
l[2].set_zorder(2)

Before definition

enter image description here

After defining zorder

enter image description here

like image 179
r-beginners Avatar answered Oct 16 '25 21:10

r-beginners


I will just put this answer here because it is a solution to the problem, but probably not the one you are looking for.

import matplotlib.pyplot as plt
import pandas as pd
import numpy as np

# generate data
df = pd.DataFrame(np.random.randint(1,10, size=(8,3)), columns=list('XYZ'))

# read columns in reverse order and plot them
# so normally, the legend will be inverted as well, but if we invert it again, you should get what you want
df[df.columns[::-1]].plot(linewidth=10, legend="reverse")

Note that in this example, you don't change the order of your data, you just read it differently, so I don't really know if that's what you want.

You can also make it easier on the eyes by creating a corresponding method.

def plot_dataframe(df: pd.DataFrame) -> None:
  df[df.columns[::-1]].plot(linewidth=10, legend="reverse")

# then you just have to call this
df = pd.DataFrame(np.random.randint(1,10, size=(8,3)), columns=list('XYZ'))
plot_dataframe(df)
like image 34
SpaceBurger Avatar answered Oct 16 '25 23:10

SpaceBurger



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!