Search code examples
pythonpandasmatplotlibpie-chart

Legend for a pie chart


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


Solution

  • 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