Функция hist
ведет себя именно так, как и должно быть.По умолчанию он разделяет данные, которые вы передаете, на 10 ячеек, причем левый край первого бина соответствует минимальному значению данных, а правый край последнего бина - максимальный.На приведенной ниже диаграмме показаны случайно сгенерированные данные, сгруппированные таким образом, с красными пунктирными линиями, обозначающими края контейнеров.

Способ обойти этоопределить края бина самостоятельно, с небольшим изменением минимального и максимального значений, чтобы центрировать столбцы по галочкам оси x.Это может быть сделано довольно легко с помощью функции linspace
numpy (в качестве примера используется столбец A в случайно сгенерированном фрейме данных):
bins = np.linspace(df["A"].min() - .5, df["A"].max() + .5, 6)
df["A"].hist(bins=bins)
Мы запрашиваем 6 значений, потому что мы определяем bin ребра , это приведет к 5 ячейкам, как показано на этом графике:

Если вы хотите сохранить промежутки между стержнями, выможет увеличить количество бинов до 9 и немного отрегулировать смещение, но это не сработает во всех случаях (здесь работает, потому что каждое значение равно 1, 2, 3, 4 или 5).
bins = np.linspace(df["A"].min() - .25, df["A"].max() + .25, 10)
df["A"].hist(bins=bins)

Наконец, так как эти данные содержат дискретные значения и вы действительно строите графики, вы можете использовать функцию value_counts
, чтобы создать серию, которую затем можно построить.в виде гистограммы:
df["A"].value_counts().sort_index().plot(kind="bar")
# Provide a 'color' argument if you need all of the bars to look the same.
df["A"].value_counts().sort_index().plot(kind="bar", color="steelblue")
