Guforu
Guforu

Reputation: 4023

Xticks by pandas plot, rename with the string

I have this df:

df = pd.DataFrame({'A': [1, 2, 3], 'B': [2, 3, 5], 'C': ['name 1', 'name 2', 'name 3']})
   A  B       C
0  1  2  name 1
1  2  3  name 2
2  3  5  name 3

What is it the correct way to plot column A and use column C as xticks?

These do not work:

df['A'].plot(xticks='C')
df['A'].plot(xticks=df['C'])

This changes the xticks but not the labels:

df['A'].plot(xticks=[1,2,3])

Should I really convert to sequence? I have also some modification of the question. I got next Error message:

ValueError: could not convert string to float: name 3

In short, I have a column of strings and want to use it as xticks for my plot.

PS: It doesn't look like there's a direct pandas plot function. I found a solution here.

Upvotes: 47

Views: 173246

Answers (3)

cottontail
cottontail

Reputation: 23131

When you call plot(), you can pass column names as axis values to use its values as tick labels. So for the question in the OP, the following works.

df.plot(y='A', x='C', legend=False);

or you can set column C as index and just call plot on column A:

df.set_index('C')['A'].plot();

res1

You can also plot multiple column values in one plot by passing a list of column names:

df.plot(y=['A', 'B'], x='C');

res2

Upvotes: 0

tdy
tdy

Reputation: 41327

As of matplotlib 3.5.0

Use ax.set_xticks with the new labels param to set ticks and labels simultaneously:

ax = df.plot(y='A')
ax.set_xticks(ticks=df.index, labels=df.C)
#                             ^^^^^^

Or, since df.plot returns an Axes object, we can chain it:

df.plot(y='A').set_xticks(df.index, df.C)

Note that plt.xticks always had a labels param, so this change just unifies the Axes and pyplot APIs.

Upvotes: 6

Alnilam
Alnilam

Reputation: 3411

The link you provided is a good resource, but shows the whole thing being done in matplotlib.pyplot and uses .subplots() to get to the axes. While I've done this before, I keep searching for ways to just use the built-into-pandas .plot() function as much as possible. To me it can simplify the code and makes it easier to leverage DataFrame goodness.

There do seem to be a number of things that aren't easy to do fully inside the parameters of df.plot() by itself, though. Luckily it returns an matplotlib.AxesSubplot, which opens up a much larger range of possibilities.

I copied your data above into a DataFrame:

df = pd.read_clipboard(quotechar="'")

It looks sort-of like:

   A B  C
0  1 2 'name 1'
1  2 3 'name 2'
2  3 5 'name 3'

But, of course, much better in non table-crippled html. (Maybe SO will fix this one day).

Then all I had to do was:

ax = df.A.plot(xticks=df.index, rot=90)
ax.set_xticklabels(df.C)

If you are using IPython/Jupyter and %matplotlib inline then both of those need to be in the same cell. I had forgotten that at first and spent quite a bit of time trying to figure what was going wrong.

enter image description here

You can do it all using the ax variable:

 ax = df.A.plot()
 ax.set_xticks(df.index)
 ax.set_xticklabels(df.C, rotation=90)

but, as I mentioned, I haven't found a way to the xticklabels inside the df.plot() function parameters, which would make it possible to do this all in a single line.

The extra step to rotate the xtick labels may be extraneous in this example, but came in handy in the one I was working on when looking for this answer.

And, of course, you can plot both A and B columns together even easier:

 ax = df.plot()
 ax.set_xticks(df.index)
 ax.set_xticklabels(df.C, rotation=90)

enter image description here

Upvotes: 102

Related Questions