একটি ম্যাটপ্লোটিব বার চার্টে মান লেবেল যুক্ত করা


95

আমি এমন কিছুতে আটকে গেলাম যা মনে হয় তুলনামূলক সহজ হওয়া উচিত। আমি নীচে যে কোডটি নিয়ে আসছি তা হ'ল আমি কাজ করছি এমন একটি বৃহত প্রকল্পের উপর ভিত্তি করে একটি নমুনা। আমি সমস্ত বিবরণ পোস্ট করার কোনও কারণ দেখিনি, সুতরাং দয়া করে আমি যে তথ্য স্ট্রাকচারগুলি এনেছি তা গ্রহণ করুন।

মূলত, আমি একটি বার চার্ট তৈরি করছি এবং আমি বারগুলিতে কীভাবে মান লেবেল যুক্ত করতে পারি তা সন্ধান করতে পারি (বারের ঠিক মাঝখানে বা তার ঠিক উপরে)। ওয়েবের চারপাশে নমুনাগুলির দিকে তাকানো হয়েছে তবে আমার নিজের কোডটিতে কোনও সাফল্য নেই। আমি বিশ্বাস করি যে সমাধানটি 'টেক্সট' বা 'টীকায়িত' দিয়েই রয়েছে তবে আমি: ক) কোনটি ব্যবহার করব তা জানি না (এবং সাধারণভাবে বলতে গেলে কোনটি কখন ব্যবহার করতে হবে তা বুঝতে পারেনি)। খ) মান লেবেল উপস্থাপন করতে হয় তা দেখতে পাচ্ছে না। আপনার সাহায্যের প্রশংসা করি, নীচে আমার কোড। আগাম ধন্যবাদ!

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
pd.set_option('display.mpl_style', 'default') 
%matplotlib inline

# Bring some raw data.
frequencies = [6, 16, 75, 160, 244, 260, 145, 73, 16, 4, 1]

# In my original code I create a series and run on that, 
# so for consistency I create a series from the list.
freq_series = pd.Series.from_array(frequencies)

x_labels = [108300.0, 110540.0, 112780.0, 115020.0, 117260.0, 119500.0, 
            121740.0, 123980.0, 126220.0, 128460.0, 130700.0]

# Plot the figure.
plt.figure(figsize=(12, 8))
fig = freq_series.plot(kind='bar')
fig.set_title('Amount Frequency')
fig.set_xlabel('Amount ($)')
fig.set_ylabel('Frequency')
fig.set_xticklabels(x_labels)

4
ম্যাটপ্লটলিবের একটি ডেমো রয়েছে: matplotlib.org/example/api/barchart_demo.html
ড্যান

উত্তর:


119

প্রথমত freq_series.plotঅক্ষটি একটি চিত্র নয় যা আমার উত্তরকে আরও স্পষ্ট করে তুলতে আমি আপনার প্রদত্ত কোডটিকে অন্য কোডের উদাহরণগুলির সাথে আরও সামঞ্জস্যপূর্ণ হওয়ার axপরিবর্তে এটি উল্লেখ করার জন্য পরিবর্তন করেছি fig

প্লটটিতে উত্পাদিত বারগুলির তালিকা আপনি ax.patchesসদস্যের কাছ থেকে পেতে পারেন । তারপরে আপনি পদ্ধতিটি ব্যবহার করে লেবেল যুক্ত করতে এই matplotlibগ্যালারী উদাহরণে প্রদর্শিত কৌশলটি ব্যবহার করতে পারেন ax.text

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

# Bring some raw data.
frequencies = [6, 16, 75, 160, 244, 260, 145, 73, 16, 4, 1]
# In my original code I create a series and run on that, 
# so for consistency I create a series from the list.
freq_series = pd.Series.from_array(frequencies)

x_labels = [108300.0, 110540.0, 112780.0, 115020.0, 117260.0, 119500.0,
            121740.0, 123980.0, 126220.0, 128460.0, 130700.0]

# Plot the figure.
plt.figure(figsize=(12, 8))
ax = freq_series.plot(kind='bar')
ax.set_title('Amount Frequency')
ax.set_xlabel('Amount ($)')
ax.set_ylabel('Frequency')
ax.set_xticklabels(x_labels)

rects = ax.patches

# Make some labels.
labels = ["label%d" % i for i in xrange(len(rects))]

for rect, label in zip(rects, labels):
    height = rect.get_height()
    ax.text(rect.get_x() + rect.get_width() / 2, height + 5, label,
            ha='center', va='bottom')

এটি এমন লেবেলযুক্ত প্লট তৈরি করে যা দেখে মনে হয়:

এখানে চিত্র বর্ণনা লিখুন


হাই সাইমন! প্রথমে, উত্তর দেওয়ার জন্য অনেক ধন্যবাদ! দ্বিতীয়ত, আমি অনুমান করি যে আমি অস্পষ্ট ছিলাম - আমি y- মানটি প্রদর্শন করতে চেয়েছিলাম। আমি কেবলমাত্র জিপ (,) এর ফ্রিকোয়েন্সি সহ লেবেলগুলি প্রতিস্থাপন করেছি। এখন, আপনি কি ডুমুর বনাম কুড়াল সম্পর্কে আরও কিছু আলোকপাত করতে পারেন? আমাকে বিভ্রান্ত করেছে। গুগ অনুসন্ধানের জন্য এটি একটি সামান্য জেনেরিক হিসাবে ভাল অনুসন্ধান বাক্যাংশ / সংস্থান পাশাপাশি দুর্দান্তও হবে। অনেক প্রশংসিত!
অপ্টটাইম

চিত্রটি এক বা একাধিক অক্ষের সংকলন, উদাহরণস্বরূপ matplotlib.org/example/statistics/… এই উদাহরণে এটি 4 টি পৃথক অক্ষ দ্বারা গঠিত একটি চিত্র।
সাইমন গিবনস

আবার ধন্যবাদ. আপনি দয়া করে টীকা এবং পাঠ্যের মধ্যে পার্থক্য বুঝতে আমাকে সহায়তা করতে পারেন? ধন্যবাদ!
অপ্টটাইম

4
উভয়ই প্লটটিতে পাঠ্য যুক্ত করতে ব্যবহৃত হতে পারে। textপ্লটটিতে কেবল কিছু পাঠ্য মুদ্রণ করে, annotateআপনি এমন সহায়িকা যা আপনি সহজেই পাঠ্যের দ্বারা নির্দিষ্ট হওয়া প্লটের নির্দিষ্ট বিন্দুটি নির্দেশ করে পাঠ্য থেকে একটি তীর যুক্ত করতে পারেন।
সাইমন গিবনস

10
সুন্দর সমাধান। আমি এখানে একটি ব্লগ পোস্ট লিখেছিলাম যা সমাধানটির উপর ভিত্তি করে তৈরি করে এবং আরও খানিকটা শক্তিশালী সংস্করণ দেয় যা অক্ষের উচ্চতা অনুসারে স্কেল করে, তাই একই কোড বিভিন্ন অক্ষের উচ্চতাযুক্ত বিভিন্ন প্লটের জন্য কাজ করে: কম্পোজিশন.াল / ব্লগ
11/29

65

অন্য প্রশ্নের এই উত্তরে বর্ণিত একটি বৈশিষ্ট্যের ভিত্তিতে আমি একটি বারের চার্টে লেবেল রাখার জন্য খুব সাধারণভাবে প্রয়োগযোগ্য সমাধান পেয়েছি।

দুর্ভাগ্যক্রমে অন্যান্য সমাধানগুলি অনেক ক্ষেত্রে কার্যকর হয় না, কারণ লেবেল এবং বারের মধ্যে ব্যবধানটি হয় বারের পরম ইউনিটে দেওয়া হয় বা বারের উচ্চতা দ্বারা মাপানো হয় । প্রাক্তনটি কেবলমাত্র সংকীর্ণ মানের জন্য কাজ করে এবং পরেরটি একটি প্লটের মধ্যে বেমানান ফাঁক দেয়। উভয়ই লগারিদমিক অক্ষগুলির সাথে ভালভাবে কাজ করে না।

আমি প্রস্তাবিত সমাধানটি স্কেল থেকে স্বতন্ত্রভাবে কাজ করে (অর্থাত্ ছোট এবং বড় সংখ্যক জন্য) এবং এমনকি সঠিকভাবে নেতিবাচক মানগুলির জন্য এবং লগারিদমিক স্কেলগুলির সাথে লেবেল রাখে কারণ এটি pointsঅফসেটের জন্য ভিজ্যুয়াল ইউনিট ব্যবহার করে।

আমি এই জাতীয় ক্ষেত্রে লেবেলের সঠিক স্থান প্রদর্শনের জন্য একটি নেতিবাচক সংখ্যা যুক্ত করেছি।

প্রতিটি বারের উচ্চতার মান এটির জন্য লেবেল হিসাবে ব্যবহৃত হয়। অন্যান্য লেবেলগুলি সহজেই সাইমনের for rect, label in zip(rects, labels)স্নিপেটের সাথে ব্যবহার করা যেতে পারে ।

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

# Bring some raw data.
frequencies = [6, -16, 75, 160, 244, 260, 145, 73, 16, 4, 1]

# In my original code I create a series and run on that,
# so for consistency I create a series from the list.
freq_series = pd.Series.from_array(frequencies)

x_labels = [108300.0, 110540.0, 112780.0, 115020.0, 117260.0, 119500.0,
            121740.0, 123980.0, 126220.0, 128460.0, 130700.0]

# Plot the figure.
plt.figure(figsize=(12, 8))
ax = freq_series.plot(kind='bar')
ax.set_title('Amount Frequency')
ax.set_xlabel('Amount ($)')
ax.set_ylabel('Frequency')
ax.set_xticklabels(x_labels)


def add_value_labels(ax, spacing=5):
    """Add labels to the end of each bar in a bar chart.

    Arguments:
        ax (matplotlib.axes.Axes): The matplotlib object containing the axes
            of the plot to annotate.
        spacing (int): The distance between the labels and the bars.
    """

    # For each bar: Place a label
    for rect in ax.patches:
        # Get X and Y placement of label from rect.
        y_value = rect.get_height()
        x_value = rect.get_x() + rect.get_width() / 2

        # Number of points between bar and label. Change to your liking.
        space = spacing
        # Vertical alignment for positive values
        va = 'bottom'

        # If value of bar is negative: Place label below bar
        if y_value < 0:
            # Invert space to place label below
            space *= -1
            # Vertically align label at top
            va = 'top'

        # Use Y value as label and format number with one decimal place
        label = "{:.1f}".format(y_value)

        # Create annotation
        ax.annotate(
            label,                      # Use `label` as label
            (x_value, y_value),         # Place label at end of the bar
            xytext=(0, space),          # Vertically shift label by `space`
            textcoords="offset points", # Interpret `xytext` as offset in points
            ha='center',                # Horizontally center label
            va=va)                      # Vertically align label differently for
                                        # positive and negative values.


# Call the function above. All the magic happens there.
add_value_labels(ax)

plt.savefig("image.png")

সম্পাদনা করুন: বার্নহিল্লেকের পরামর্শ অনুসারে আমি কোনও ফাংশনে প্রাসঙ্গিক কার্যকারিতাটি বের করেছি

এটি নিম্নলিখিত আউটপুট উত্পাদন করে:

প্রতিটি বারে স্বয়ংক্রিয়ভাবে স্থাপন করা লেবেলগুলির সাথে বার চার্ট

এবং লগারিদমিক স্কেল (এবং লগারিদমিক স্কেলিং প্রদর্শনের জন্য ইনপুট ডেটাতে কিছু সমন্বয়) সহ, এটি ফলাফল:

প্রতিটি বারে স্বয়ংক্রিয়ভাবে স্থাপন করা লেবেল সহ লগারিদমিক স্কেল সহ বার চার্ট


4
চমত্কার উত্তর! ধন্যবাদ এটি নির্মিত বার প্লটিংয়ে পান্ডার সাথে নির্বিঘ্নে কাজ করেছিল।
m4p85r

4
প্রস্তাবিত উন্নতি: plt.annotate পরিবর্তে ax.annotate ব্যবহার করুন। এই পরিবর্তনটি পুরো রুটিনকে এমন একটি ফাংশনে আবদ্ধ করার অনুমতি দেবে যা অক্ষ অক্ষের পাশ দিয়ে যায়, যা পরে দরকারী স্ট্যান্ডেলোন প্লট ইউটিলিটি ফাংশনে রূপান্তরিত হতে পারে।
বার্নহিলিক

@ বার্নহিল্লেক, পরামর্শের জন্য ধন্যবাদ। আমি আমার সম্পাদনায় ঠিক তা করেছি। দ্রষ্টব্য, এটি বর্তমানে কেবল উল্লম্ব বারের চার্টের সাথে কাজ করে এবং অন্য কোনও ধরণের প্লটের (সম্ভবত হিস্টোগ্রাম সহ) ব্যবহার করে না। ফাংশনটিকে আরও জেনেরিক তৈরি করা বোঝা আরও শক্ত করে তোলে এবং এখানে উত্তরের জন্য কম উপযোগী হয়।
justfortherec

আমি অন্যদের চেয়ে খুব শক্ত উত্তর। মন্তব্য দ্বারা প্রতিটি লাইন সুন্দরভাবে ব্যাখ্যা আমাকে পুরো ধারণা একীভূত করতে সাহায্য করুন।
কোড_কুনড্রাম

34

উপরের (দুর্দান্ত!) উত্তরটি তৈরি করে আমরা কয়েকটি সামঞ্জস্য রেখে একটি অনুভূমিক বারের প্লটও তৈরি করতে পারি:

# Bring some raw data.
frequencies = [6, -16, 75, 160, 244, 260, 145, 73, 16, 4, 1]

freq_series = pd.Series(frequencies)

y_labels = [108300.0, 110540.0, 112780.0, 115020.0, 117260.0, 119500.0, 
            121740.0, 123980.0, 126220.0, 128460.0, 130700.0]

# Plot the figure.
plt.figure(figsize=(12, 8))
ax = freq_series.plot(kind='barh')
ax.set_title('Amount Frequency')
ax.set_xlabel('Frequency')
ax.set_ylabel('Amount ($)')
ax.set_yticklabels(y_labels)
ax.set_xlim(-40, 300) # expand xlim to make labels easier to read

rects = ax.patches

# For each bar: Place a label
for rect in rects:
    # Get X and Y placement of label from rect.
    x_value = rect.get_width()
    y_value = rect.get_y() + rect.get_height() / 2

    # Number of points between bar and label. Change to your liking.
    space = 5
    # Vertical alignment for positive values
    ha = 'left'

    # If value of bar is negative: Place label left of bar
    if x_value < 0:
        # Invert space to place label to the left
        space *= -1
        # Horizontally align label at right
        ha = 'right'

    # Use X value as label and format number with one decimal place
    label = "{:.1f}".format(x_value)

    # Create annotation
    plt.annotate(
        label,                      # Use `label` as label
        (x_value, y_value),         # Place label at end of the bar
        xytext=(space, 0),          # Horizontally shift label by `space`
        textcoords="offset points", # Interpret `xytext` as offset in points
        va='center',                # Vertically center label
        ha=ha)                      # Horizontally align label differently for
                                    # positive and negative values.

plt.savefig("image.png")

টীকা সহ অনুভূমিক বারের প্লট


4
গ্রিডটি প্রদর্শনের জন্য:freq_series.plot(kind='barh', grid=True)
sinapan

এমনকি গ্রুপ বার-চার্ট সহ পুরোপুরি কাজ করে। ধন্যবাদ
প্রবাহ

অনুভূমিক বারের গ্রাফটি দিয়ে সুন্দরভাবে সম্পন্ন!
কোড_কুনড্রাম

আমার জন্য, বারগুলি চার্টের চারপাশে থাকা বাক্সের সাথে সংখ্যাগুলি ছেদ করছে। এই সমস্যা এড়ানোর জন্য একটি উপায় আছে কি?
bweber13

ব্যবহার করে আমার নিজের সমস্যার সমাধানax.set_xlim([0, 1.1*max_value])
bweber13

14

আপনি যদি বারের উপরে ডেটা পয়েন্টগুলি কেবল লেবেল করতে চান তবে আপনি plt.annotate () ব্যবহার করতে পারেন

আমার কোড:

import numpy as np
import matplotlib.pyplot as plt

n = [1,2,3,4,5,]
s = [i**2 for i in n]
line = plt.bar(n,s)
plt.xlabel('Number')
plt.ylabel("Square")

for i in range(len(s)):
    plt.annotate(str(s[i]), xy=(n[i],s[i]), ha='center', va='bottom')

plt.show()

একটি অনুভূমিক এবং উল্লম্ব সারিবদ্ধ নির্দিষ্ট করে 'center'এবং 'bottom'যথাক্রমে একজন কেন্দ্রিক টীকাগুলি পেতে পারেন।

একটি লেবেলযুক্ত বার চার্ট


4
পরিষ্কার এবং সহজ
ইথান ইয়াঞ্জিয়া লি

আমরা কীভাবে লেবেলটিকে সঠিক কেন্দ্রে রাখতে পারি তা আপনি যুক্ত করতে পারেন?
x89

@ x89 আপনি পাঠ্যটির অনুভূমিক এবং উলম্ব সারিবদ্ধতা নির্দিষ্ট করতে পারবেন যা কেন্দ্র করে does - আমি উত্তরটি এটির সাথে উন্নত করতে সম্পাদনা করেছি।
সাইমন গিবনস

0

আপনি যদি বারগুলির উপরে কেবল ডেটাপয়েন্টগুলি যুক্ত করতে চান তবে আপনি এটি সহ সহজেই এটি করতে পারেন:

 for i in range(len(frequencies)): # your number of bars
    plt.text(x = x_values[i]-0.25, #takes your x values as horizontal positioning argument 
    y = y_values[i]+1, #takes your y values as vertical positioning argument 
    s = data_labels[i], # the labels you want to add to the data
    size = 9) # font size of datalabels
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.