Could you please explain why vertical grid lines not match points?
Here is my data for plot:
{datetime.datetime(2025, 4, 15, 19, 23, 50, 658000, tzinfo=datetime.timezone.utc): 68.0, datetime.datetime(2025, 4, 16, 19, 31, 1, 367000, tzinfo=datetime.timezone.utc): 72.0, datetime.datetime(2025, 4, 17, 19, 34, 21, 507000, tzinfo=datetime.timezone.utc): 75.0, datetime.datetime(2025, 4, 18, 19, 50, 28, 446000, tzinfo=datetime.timezone.utc): 80.0, datetime.datetime(2025, 4, 19, 19, 57, 15, 393000, tzinfo=datetime.timezone.utc): 78.0, datetime.datetime(2025, 4, 20, 19, 57, 49, 60000, tzinfo=datetime.timezone.utc): 77.0, datetime.datetime(2025, 4, 21, 20, 28, 51, 127710, tzinfo=datetime.timezone.utc): 73.0}
And here is my code:
fig, ax = plt.subplots(figsize=(12, 6))
ax.plot(df['Дата'], df['Вес'], marker='o', linestyle='-', color='royalblue', label='Вес')
ax.scatter(df['Дата'], df['Вес'], color='red', zorder=5)
ax.set_title('График изменения веса по дням', fontsize=16)
ax.set_xlabel('Дата', fontsize=12)
ax.set_ylabel('Вес (кг)', fontsize=12)
ax.xaxis.set_major_locator(mdates.AutoDateLocator()) # Раз в день
ax.xaxis.set_major_formatter(mdates.DateFormatter('%d.%m.%Y'))
plt.setp(ax.xaxis.get_majorticklabels(), rotation=45, ha="right")
ax.grid(True, linestyle='--', alpha=0.6)
plt.tight_layout()
There are multiple solutions for it.
I think using ax.set_xticks(df['Дата']) "to force the ticks to match your actual datetimes" might be better for you when the time of day matters, not just the date.
The full code:
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import pandas as pd
from datetime import datetime, timezone
data = {
datetime(2025, 4, 15, 19, 23, 50, 658000, tzinfo=timezone.utc): 68.0,
datetime(2025, 4, 16, 19, 31, 1, 367000, tzinfo=timezone.utc): 72.0,
datetime(2025, 4, 17, 19, 34, 21, 507000, tzinfo=timezone.utc): 75.0,
datetime(2025, 4, 18, 19, 50, 28, 446000, tzinfo=timezone.utc): 80.0,
datetime(2025, 4, 19, 19, 57, 15, 393000, tzinfo=timezone.utc): 78.0,
datetime(2025, 4, 20, 19, 57, 49, 60000, tzinfo=timezone.utc): 77.0,
datetime(2025, 4, 21, 20, 28, 51, 127710, tzinfo=timezone.utc): 73.0
}
df = pd.DataFrame(list(data.items()), columns=['Дата', 'Вес'])
fig, ax = plt.subplots(figsize=(12, 6), layout='constrained')
ax.plot(df['Дата'], df['Вес'],
marker='o',
markersize=8,
markerfacecolor='red',
markeredgecolor='white',
markeredgewidth=1.5,
linestyle='-',
linewidth=2,
color='royalblue',
label='Вес')
ax.set_xticks(df['Дата'])
date_fmt = mdates.DateFormatter('%d.%m.%Y\n%H:%M')
ax.xaxis.set_major_formatter(date_fmt)
ax.grid(True,
which='major',
linestyle='--',
linewidth=0.7,
alpha=0.7)
ax.set_title('График изменения веса по дням', fontsize=16, pad=20)
ax.set_xlabel('Дата и время измерения', fontsize=12, labelpad=10)
ax.set_ylabel('Вес (кг)', fontsize=12, labelpad=10)
ax.tick_params(axis='x', which='major', rotation=45, labelsize=10)
fig.autofmt_xdate(ha='center', bottom=0.2)
plt.show()
Another solution is "normalizing datetime to midnight" using df['Дата'] = df['Дата'].dt.normalize(). It might be better when time is not required. You’re plotting daily trends.
The full code:
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import pandas as pd
import datetime
data = {
datetime.datetime(2025, 4, 15, 19, 23, 50, 658000, tzinfo=datetime.timezone.utc): 68.0,
datetime.datetime(2025, 4, 16, 19, 31, 1, 367000, tzinfo=datetime.timezone.utc): 72.0,
datetime.datetime(2025, 4, 17, 19, 34, 21, 507000, tzinfo=datetime.timezone.utc): 75.0,
datetime.datetime(2025, 4, 18, 19, 50, 28, 446000, tzinfo=datetime.timezone.utc): 80.0,
datetime.datetime(2025, 4, 19, 19, 57, 15, 393000, tzinfo=datetime.timezone.utc): 78.0,
datetime.datetime(2025, 4, 20, 19, 57, 49, 60000, tzinfo=datetime.timezone.utc): 77.0,
datetime.datetime(2025, 4, 21, 20, 28, 51, 127710, tzinfo=datetime.timezone.utc): 73.0,
}
df = pd.DataFrame(list(data.items()), columns=["Дата", "Вес"])
df['Дата'] = df['Дата'].dt.tz_convert(None).dt.normalize()
fig, ax = plt.subplots(figsize=(12, 6))
ax.plot(df['Дата'], df['Вес'], marker='o', linestyle='-', color='royalblue', label='Вес')
ax.scatter(df['Дата'], df['Вес'], color='red', zorder=5)
ax.set_title('График изменения веса по дням', fontsize=16)
ax.set_xlabel('Дата', fontsize=12)
ax.set_ylabel('Вес (кг)', fontsize=12)
ax.xaxis.set_major_locator(mdates.DayLocator())
ax.xaxis.set_major_formatter(mdates.DateFormatter('%d.%m.%Y'))
plt.setp(ax.xaxis.get_majorticklabels(), rotation=45, ha="right")
ax.grid(True, linestyle='--', alpha=0.6)
plt.tight_layout()
plt.show()
If none of the solutions is not functional for you, please inform me and I will attempt to provide other solution.
Output: