4

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

0

2 Answers 2

6

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

Sign up to request clarification or add additional context in comments.

Comments

1

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)

1 Comment

Thanks @spacebrger that's a useful solution but as you said not quite what i was looking for - i didn't know about that legend option either, so thanks for that too!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy 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.