Cara memplot beberapa batang di matplotlib, ketika saya mencoba memanggil fungsi batang beberapa kali, mereka tumpang tindih dan seperti yang terlihat pada gambar di bawah ini, nilai tertinggi merah hanya dapat dilihat. Bagaimana cara memplot beberapa batang dengan tanggal di sumbu x?
Sejauh ini, saya mencoba ini:
import matplotlib.pyplot as plt
import datetime
x = [
datetime.datetime(2011, 1, 4, 0, 0),
datetime.datetime(2011, 1, 5, 0, 0),
datetime.datetime(2011, 1, 6, 0, 0)
]
y = [4, 9, 2]
z = [1, 2, 3]
k = [11, 12, 13]
ax = plt.subplot(111)
ax.bar(x, y, width=0.5, color='b', align='center')
ax.bar(x, z, width=0.5, color='g', align='center')
ax.bar(x, k, width=0.5, color='r', align='center')
ax.xaxis_date()
plt.show()
Saya mengerti:
Hasilnya harus seperti ini, tetapi dengan tanggal berada di sumbu x dan batang bersebelahan:
python
matplotlib
John Smith
sumber
sumber
Jawaban:
import matplotlib.pyplot as plt from matplotlib.dates import date2num import datetime x = [ datetime.datetime(2011, 1, 4, 0, 0), datetime.datetime(2011, 1, 5, 0, 0), datetime.datetime(2011, 1, 6, 0, 0) ] x = date2num(x) y = [4, 9, 2] z = [1, 2, 3] k = [11, 12, 13] ax = plt.subplot(111) ax.bar(x-0.2, y, width=0.2, color='b', align='center') ax.bar(x, z, width=0.2, color='g', align='center') ax.bar(x+0.2, k, width=0.2, color='r', align='center') ax.xaxis_date() plt.show()
Saya tidak tahu apa artinya "nilai y juga tumpang tindih", apakah kode berikut menyelesaikan masalah Anda?
ax = plt.subplot(111) w = 0.3 ax.bar(x-w, y, width=w, color='b', align='center') ax.bar(x, z, width=w, color='g', align='center') ax.bar(x+w, k, width=w, color='r', align='center') ax.xaxis_date() ax.autoscale(tight=True) plt.show()
sumber
autofmt_xdate()
, yang memutar label secara otomatis.Masalah dengan menggunakan tanggal sebagai nilai x, adalah jika Anda menginginkan diagram batang seperti di gambar kedua, hasilnya salah. Anda sebaiknya menggunakan diagram batang bertumpuk (warna di atas satu sama lain) atau mengelompokkan menurut tanggal (tanggal "palsu" pada sumbu x, pada dasarnya hanya mengelompokkan titik data).
import numpy as np import matplotlib.pyplot as plt N = 3 ind = np.arange(N) # the x locations for the groups width = 0.27 # the width of the bars fig = plt.figure() ax = fig.add_subplot(111) yvals = [4, 9, 2] rects1 = ax.bar(ind, yvals, width, color='r') zvals = [1,2,3] rects2 = ax.bar(ind+width, zvals, width, color='g') kvals = [11,12,13] rects3 = ax.bar(ind+width*2, kvals, width, color='b') ax.set_ylabel('Scores') ax.set_xticks(ind+width) ax.set_xticklabels( ('2011-Jan-4', '2011-Jan-5', '2011-Jan-6') ) ax.legend( (rects1[0], rects2[0], rects3[0]), ('y', 'z', 'k') ) def autolabel(rects): for rect in rects: h = rect.get_height() ax.text(rect.get_x()+rect.get_width()/2., 1.05*h, '%d'%int(h), ha='center', va='bottom') autolabel(rects1) autolabel(rects2) autolabel(rects3) plt.show()
sumber
datetime64
: misalnya satu bulan senilai:np.arange('2012-02', '2012-03', dtype='datetime64[D]')
. Anda mungkin perlu berpikir lebih keras tentang cara terbaik untuk merepresentasikan data ini jika Anda memiliki 40 set data (sesuai komentar lainnya) yang mencakup lebih dari 100 hari.xaxis_date
tetapi Anda harus menyesuaikan apa yang telah saya tulis untuk mengimbangi nilai tanggal Anda (misalnya dengan menggunakan beberapa jamtimedelta
) untuk setiap seri agar tidak tumpang tindih. Jawaban lain hanya melakukan ini, tetapi Anda mungkin perlu mengosongkan label sesudahnya.Saya tahu ini tentang
matplotlib
, tetapi menggunakanpandas
danseaborn
dapat menghemat banyak waktu:df = pd.DataFrame(zip(x*3, ["y"]*3+["z"]*3+["k"]*3, y+z+k), columns=["time", "kind", "data"]) plt.figure(figsize=(10, 6)) sns.barplot(x="time", hue="kind", y="data", data=df) plt.show()
sumber
setelah mencari solusi serupa dan tidak menemukan sesuatu yang cukup fleksibel, saya memutuskan untuk menulis fungsi saya sendiri untuk itu. Ini memungkinkan Anda untuk memiliki batang per grup sebanyak yang Anda inginkan dan menentukan lebar grup serta lebar individu batang di dalam grup.
Nikmati:
from matplotlib import pyplot as plt def bar_plot(ax, data, colors=None, total_width=0.8, single_width=1, legend=True): """Draws a bar plot with multiple bars per data point. Parameters ---------- ax : matplotlib.pyplot.axis The axis we want to draw our plot on. data: dictionary A dictionary containing the data we want to plot. Keys are the names of the data, the items is a list of the values. Example: data = { "x":[1,2,3], "y":[1,2,3], "z":[1,2,3], } colors : array-like, optional A list of colors which are used for the bars. If None, the colors will be the standard matplotlib color cyle. (default: None) total_width : float, optional, default: 0.8 The width of a bar group. 0.8 means that 80% of the x-axis is covered by bars and 20% will be spaces between the bars. single_width: float, optional, default: 1 The relative width of a single bar within a group. 1 means the bars will touch eachother within a group, values less than 1 will make these bars thinner. legend: bool, optional, default: True If this is set to true, a legend will be added to the axis. """ # Check if colors where provided, otherwhise use the default color cycle if colors is None: colors = plt.rcParams['axes.prop_cycle'].by_key()['color'] # Number of bars per group n_bars = len(data) # The width of a single bar bar_width = total_width / n_bars # List containing handles for the drawn bars, used for the legend bars = [] # Iterate over all data for i, (name, values) in enumerate(data.items()): # The offset in x direction of that bar x_offset = (i - n_bars / 2) * bar_width + bar_width / 2 # Draw a bar for every value of that type for x, y in enumerate(values): bar = ax.bar(x + x_offset, y, width=bar_width * single_width, color=colors[i % len(colors)]) # Add a handle to the last drawn bar, which we'll need for the legend bars.append(bar[0]) # Draw legend if we need if legend: ax.legend(bars, data.keys()) if __name__ == "__main__": # Usage example: data = { "a": [1, 2, 3, 2, 1], "b": [2, 3, 4, 3, 1], "c": [3, 2, 1, 4, 2], "d": [5, 9, 2, 1, 8], "e": [1, 3, 2, 2, 3], "f": [4, 3, 1, 1, 4], } fig, ax = plt.subplots() bar_plot(ax, data, total_width=.8, single_width=.9) plt.show()
Keluaran:
sumber
xticks
plot, misalnyaplt.xticks(range(5), ["one", "two", "three", "four", "five"])
Saya melakukan solusi ini: jika Anda ingin plot lebih dari satu plot dalam satu gambar, pastikan sebelum plot plot berikutnya Anda telah mengatur hak
matplotlib.pyplot.hold(True)
untuk dapat menambahkan plot lain.Mengenai nilai datetime pada sumbu X, solusi yang menggunakan penyelarasan batang berfungsi untuk saya. Saat Anda membuat plot batang lain dengan
matplotlib.pyplot.bar()
, cukup gunakanalign='edge|center'
dan aturwidth='+|-distance'
.Jika Anda menyetel semua batang (plot) dengan benar, Anda akan melihat batangnya baik-baik saja.
sumber
matplotlib.pyplot.hold
sudah tidak digunakan lagi sejak v2.0, seperti yang disebutkan di dokumen