1

With a dataframe structured loosely in the way shown below.

                                       ID  Price  ColorID
Datetime                                                 
2020-10-30 07:21:00.074000+00:00   131310  13.13        0
2020-10-30 07:21:00.485128+00:00  5250455  13.02        1
2020-10-30 07:21:00.485000+00:00   130210  13.02        0
2020-10-30 07:21:00.486000+00:00   130110  13.01        0
2020-10-30 07:21:00.486000+00:00   130310  13.03        0
2020-10-30 07:21:00.488000+00:00   130310  13.03        0 

I'm trying to draw price progression per ID, with the colorID defining the color to plot in.

If I don't use any colors, the below command will give me the plot I am looking for, but with an inbuilt color scheme, rather than the one I'm requiring..

test.groupby("ID").Price.plot(drawstyle="steps-post", marker="d", linewidth=2)

Same ID will retain same colorID, so first trial has been to first create a grouped object, then refer to that grouped object to try and obtain a color scheme.

grouped = test.groupby("ID")
colors = {0: "b", 1: "r"}
grouped.Price.plot(drawstyle="steps-post", marker="d", linewidth=2, c=colors[grouped.ColorID.last()])

which runs into the error:

TypeError: 'Series' objects are mutable, thus they cannot be hashed

whereas trying to go after a direct application through

grouped.Price.plot(drawstyle="steps-post", marker="d", linewidth=2,c=np.where(grouped.ColorID==0,"b","r"))

will try to read the color array as RGB channel, hence resulting in

ValueError: Invalid RGBA argument: array('r', dtype='<U1')

Is there a straightforward way I'm blatantly missing, or am I consigned to either making multi-label groups or plotting 1 by 1 in a for loop, specifying the plot handles outside the loop?

1 Answer 1

1

I know you are hesitant to for loop, but it's not really a bad thing. It provides you more control on how the plot looks. Plus, I doubt that you get any vectorization with groupby().plot().

So a for loop would look like:

colors = {0: "b", 1: "r"}

grouped = test.groupby("ID")

fig, ax = plt.subplots()
for k, g in grouped:
    color = colors[g['ColorID'].iloc[0]]
    g.Price.plot(drawstyle="steps-post", marker="d", 
                 linewidth=2, c=color,
                 label=k, ax=ax)

ax.legend()

Output:

enter image description here

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

3 Comments

You are probably right that internally a for loop is used anyway, and I should just use it explicitly under my own control rather than under the hood. Thanks.
One issue with doing it in the subplots way, however, is that I can't really make a hovering annotation for if I wish to check in-plot which ID I'm looking at.
@Uvar That's just my usual way to plot. You can skip all subplots related code.

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.