0

I would like to create a legend with labels and values. The dataset contains this column

ID          LETTER
    2        C
    26       C
    40       C
    63       D
    83       E
    139      C
    141      E
    145      C
    148      E
    156      E

I am using a pie chart:

from itertools import chain
from collections import Counter
import matplotlib.pyplot as plt

plt.figure(figsize=(16,8))

cts = Counter(chain.from_iterable(df.LETTER.str.split('|').values))
_ = plt.pie(cts.values(), labels=cts.keys(), autopct='%1.1f%%')

patches = cts.values()
labels = cts.keys()

sort_legend = True
if sort_legend:
   patches,labels, dummy =  zip(*sorted(zip(patches, labels, df.LETTER),
                                          key=lambda x: x[2],
                                          reverse=True))
    
plt.legend(cts.values(), labels=cts.keys(), loc='center left', bbox_to_anchor=(-0.1, 1.),
           fontsize=8)

Running the above code, I get a legend table which does not contain any value, but only labels. I would like to not have any labels or values in the pie chart, but only within the legend. Can you tell me how to fix the code?

Thanks

enter image description here

V_sqrt
  • 537
  • 8
  • 28
  • Why don't we just stop displaying labels and percentages of values? `_ = plt.pie(cts.values())` – r-beginners Feb 16 '21 at 01:52
  • @r.beginniers, I have already tried it, but the problem is that in the legend I am not able to see the values. Even I callout it would be ok – V_sqrt Feb 16 '21 at 01:54
  • Is it possible to share the current output graphs? Also, what does this do?`df.LETTER.str.split('|').values` – r-beginners Feb 16 '21 at 01:58
  • you can use df.Letter.values only. I put the cleaned text. That line of code needs to split a string in two parts. – V_sqrt Feb 16 '21 at 02:08
  • I was trying to follow these steps: https://stackoverflow.com/questions/23577505/how-to-avoid-overlapping-of-labels-autopct-in-a-matplotlib-pie-chart, but I would prefer to have callouts instead of a legend (if it could be possible and easy) – V_sqrt Feb 16 '21 at 02:20

1 Answers1

1

Is this the output you expect? I'm used to using pandas, so I'm using dataframe. I have specified the pathces and labels obtained in the referenced code.

import pandas as pd
import numpy as np
import io

data = '''
ID          LETTER
    2        C
    26       C
    40       C
    63       O
    83       N
    139      C
    141      O
    145      C
    148      N
    156      N
'''

df = pd.read_csv(io.StringIO(data), delim_whitespace=True)


from itertools import chain
from collections import Counter
import matplotlib.pyplot as plt

fig = plt.figure(figsize=(4,3),dpi=144)
ax = fig.add_subplot(111)

cts = df.LETTER.value_counts().to_frame()
percent = 100.*cts.LETTER / cts.LETTER.sum()
ax.pie(cts.LETTER)

patches = cts.index
labels = ['{0} - {1:1.2f} %'.format(i,j) for i,j in zip(cts.index, percent)]

sort_legend = True
if sort_legend:
    patches,labels, dummy =  zip(*sorted(zip(patches, labels, df.LETTER),
                                          key=lambda x: x[2],
                                          reverse=True))

plt.legend(patches, labels=labels, loc='center left', bbox_to_anchor=(-0.1, 1.), fontsize=8)
plt.show()

enter image description here

r-beginners
  • 31,170
  • 3
  • 14
  • 32