Как построить несколько полосок в matplotlib, когда я пытался вызвать функцию полосы несколько раз, они перекрываются, и, как видно на рисунке ниже, можно увидеть только самое высокое значение красного цвета. Как я могу нанести несколько столбцов с датами на оси x?
Пока что я пробовал это:
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()
Получил вот что:
Результат должен быть примерно таким, но с датами на оси x и столбцами рядом друг с другом:
python
matplotlib
Джон Смит
источник
источник
Ответы:
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()
Я не знаю, что означает «значения y также перекрываются». Решает ли следующий код вашу проблему?
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()
источник
autofmt_xdate()
автоматического поворота меток.Проблема с использованием дат в качестве значений x заключается в том, что если вам нужна гистограмма, как на втором рисунке, они будут неправильными. Вы должны либо использовать линейчатую диаграмму с накоплением (цвета друг над другом), либо группировать по дате («поддельная» дата на оси x, в основном просто группируя точки данных).
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()
источник
datetime64
: например , один месяц на сумму:np.arange('2012-02', '2012-03', dtype='datetime64[D]')
. Возможно, вам придется больше подумать о том, как лучше всего представить эти данные, если у вас есть 40 наборов данных (согласно другому комментарию), охватывающих более 100 дней.xaxis_date
но вам нужно будет адаптировать то, что я написал, чтобы компенсировать ваши значения даты (например, на количество часов использованияtimedelta
) для каждой серии, чтобы они не перекрывались. Другой ответ делает именно это, но вам, возможно, впоследствии придется испортить ярлыки.Я знаю, что это примерно так
matplotlib
, но использованиеpandas
иseaborn
может сэкономить вам много времени: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()
источник
После поиска аналогичного решения и не найдя ничего достаточно гибкого, я решил написать для него свою собственную функцию. Это позволяет вам иметь столько полос в группе, сколько вы хотите, и указывать как ширину группы, так и индивидуальную ширину полос внутри групп.
Наслаждаться:
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()
Выход:
источник
xticks
сюжет, напримерplt.xticks(range(5), ["one", "two", "three", "four", "five"])
Я сделал следующее решение: если вы хотите построить более одного графика на одной фигуре, убедитесь, что перед построением следующих графиков вы правильно настроили
matplotlib.pyplot.hold(True)
возможность добавления других графиков.Что касается значений даты и времени по оси X, решение с использованием выравнивания полосок у меня работает. Когда вы создаете еще одну гистограмму с помощью
matplotlib.pyplot.bar()
, просто используйтеalign='edge|center'
и установитеwidth='+|-distance'
.Когда вы установите все полосы (графики) правильно, вы увидите, что полосы в порядке.
источник
matplotlib.pyplot.hold
он устарел с версии 2.0, как упоминалось в документации,