На аналогичный вопрос отвечает здесь . Тем не менее, связанный вопрос спрашивает о графике, созданном с seaborn
, а не непосредственно с matplotlib
. Решение здесь аналогично, но требует некоторых незначительных корректировок:
import matplotlib.pyplot as plt
import numpy as np
data = np.random.normal(size=(100, 3))
fig, ax = plt.subplots(1, 1)
ax.boxplot(data)
# Loop over the 3 boxes
for i in range(3):
# Set the limits of the lower whisker to be the same as the box limits
ax.lines[i*7 + 3].set_xdata(ax.lines[i*7 + 5].get_xdata())
# Set the limits of the upper whisker to be the same as the box limits
ax.lines[i*7 + 4].set_xdata(ax.lines[i*7 + 5].get_xdata())
![enter image description here](https://i.stack.imgur.com/vYfuf.png)
Обратите внимание, что если вы передаете аргумент showfliers=False
вызову plt.boxplot
результирующие оси будут содержать только 6 строк, а не 7. Наш код должен затем стать:
for i in range(3):
ax.lines[i*6 + 3].set_xdata(ax.lines[i*6 + 5].get_xdata())
ax.lines[i*6 + 4].set_xdata(ax.lines[i*6 + 5].get_xdata())
Передача других аргументов в вызов plt.boxplot
может дополнительно изменить количество экземпляров строки нашего оси. Необходимость изменять наш код при изменении аргументов, переданных в plt.boxplot
, - боль
Лучшим решением было бы сохранить данные, возвращаемые вызовом на plt.boxplot
, и использовать это напрямую:
fig, ax = plt.subplots(1, 1)
# Keep hold of the returned
box = ax.boxplot(data)
# Loop over the 3 boxes
for i in range(3):
# Adjust the lower cap
box['caps'][2*i].set_xdata(box['boxes'][i].get_xdata()[:2])
# Adjust the upper cap
box['caps'][2*i + 1].set_xdata(box['boxes'][i].get_xdata()[:2])
Это лучше, хотя мы все еще жестко программируем 3 бокса (range(3)
). Мы можем избавиться от этого как:
fig, ax = plt.subplots(1, 1)
# Keep hold of the returned
box = ax.boxplot(data)
# Loop over the n boxes
for i, box_lines in enumerate(box['boxes']):
# Adjust the lower cap
box['caps'][2*i].set_xdata(box_lines.get_xdata()[:2])
# Adjust the upper cap
box['caps'][2*i + 1].set_xdata(box_lines.get_xdata()[:2])
Кроме того, тот же результат может быть достигнут для горизонтальных боксов, если мы вместо этого изменим ydata:
fig, ax = plt.subplots(1, 1)
box = ax.boxplot(data, vert=False)
# Loop over the n boxes
for i, box_lines in enumerate(box['boxes']):
# Adjust the lower cap
box['caps'][2*i].set_ydata(box_lines.get_ydata()[:2])
# Adjust the upper cap
box['caps'][2*i + 1].set_ydata(box_lines.get_ydata()[:2])