0

For the df below, I'm trying to alter the legend of the scatter plot to display Column C values.

It works when the values are floats but when I try to insert strings it returns a ValueError. ValueError: could not convert string to float: 'Y'

import pandas as pd
import matplotlib.pyplot as plt

d = ({
      'A' : [1,2,3,4,5,6,7,8,9,10],
      'B' : [1,1,1,2,2,2,7,7,7,7],     
     #'C' : ['X','Y','Z','X','Y','Z','A','X','Y','Z'],  #Doesn't work 
      'C' : [2,4,6,8,2,4,6,8,10,2],    # Works
      })

df = pd.DataFrame(data=d)

fig,ax = plt.subplots()

x = df['A']
y = df['B']
classes = df['C']
unique = list(set(classes))
colors = [plt.cm.jet(float(i)/max(unique)) for i in unique]
for i, u in enumerate(unique):
    xi = [x[j] for j  in range(len(x)) if classes[j] == u]
    yi = [y[j] for j  in range(len(x)) if classes[j] == u]
    plt.scatter(xi, yi, c=colors[i], label=str(u))
plt.legend()

Thus far, when trying to use the strings I've tried to change float to str (as below):

colors = [plt.cm.jet(float(i)/max(unique)) for i in unique]
colors = [plt.cm.jet(str(i)/max(unique)) for i in unique]

It returns TypeError: unsupported operand type(s) for /: 'str' and 'str'

Intended Output (But I would like to have strings in the legend, so 'X','Y','Z' instead of 2,4,6):

enter image description here

Community
  • 1
  • 1
  • You can't divide a string. That is, you can't use the operator `/` on a string like 'Z'. Also, your code `colors = [plt.cm.jet(str(i)/max(unique)) for i in unique]` is converting `i` to a string, and in that case `i` is already a string. Could you explain what you want to obtain? – nahusznaj Jul 04 '18 at 09:10
  • @nahusznaj updated –  Jul 04 '18 at 09:29
  • 1
    I updated [the answer](https://stackoverflow.com/a/42057207/4124317) from which you got the idea to be able to use strings as classes. Of course you cannot use strings for index a colormap, but need to use numbers instead. – ImportanceOfBeingErnest Jul 04 '18 at 09:41
  • I'm not sure that's what @Maxibon wanted to do and had something to add but since I can't submit an answer, here's the lines I think you could change to obtain something `colors = [plt.cm.flag(i) for i,u in enumerate(unique)]` `for i, u in enumerate(unique): xi = [x[j] for j in range(len(x)) if classes[j] == u] yi = [y[j] for j in range(len(x)) if classes[j] == u] plt.scatter(xi, yi, c=colors[i], label=str(u))` – nahusznaj Jul 04 '18 at 09:51
  • @ImportanceOfBeingErnest Thanks, spot on. –  Jul 04 '18 at 09:56
  • @nahusznaj `flag` is a cyclic colormap, I don't think this will help here, because you would want to have unique colors. In general you may of course index the colormap (calling it with integers), but that requires some prior knowledge about the number of colors in that map, so I think the proposed solution in the other answer is still more versatile in general. – ImportanceOfBeingErnest Jul 04 '18 at 11:08
  • I agree. I didn't put much thought into choosing jet for my answer. – nahusznaj Jul 04 '18 at 11:25

0 Answers0