44

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.

cottontail
  • 10,268
  • 18
  • 50
  • 51
Guforu
  • 3,835
  • 8
  • 33
  • 52

3 Answers3

100

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

Alnilam
  • 3,121
  • 2
  • 21
  • 22
  • 1
    Although it looks like you may have already gotten this answer when you asked almost the same question [here](http://stackoverflow.com/questions/23472877/plot-with-pandas-xticks?rq=1). – Alnilam May 16 '15 at 20:05
  • It seems Pandas still not offer to relabel ticks, and your solution accessing matplotlib Axes is still valid in 2021. It is a bit strange to me, as specifying text labels for ticks seems a very common need. – mins Jan 29 '21 at 11:55
  • 1
    @mins It’s way too late but fyi, if the labels are dataframe column values, then it’s possible to set tick labels in a single `plot` call. I added [an answer here](https://stackoverflow.com/a/75551827/19123103) that shows it. – cottontail Feb 24 '23 at 04:51
3

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.

tdy
  • 36,675
  • 19
  • 86
  • 83
0

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

cottontail
  • 10,268
  • 18
  • 50
  • 51