I have a plotly chart that looks like this:
Is there a way to make a second x axis that only has the years? What I mean is that I want two x axes: a 'sub-axis' that has the months (Sep, Nov, Jan , ...), and another one that has the years (2021, 2022, 2023).
It is possible to handle this by making the x-axis a multiple list, but if the original data is in date units, it will be changed to a graph of one day in month units. To put it more simply, if the data is for one year, there are 365 points, but if the data is displayed in months only, there will be 12 points. The closest way to meet the request is to make it month name and day.
import plotly.express as px
import plotly.graph_objects as go
import pandas as pd
import calendar
df = px.data.stocks()
df['date'] = pd.to_datetime(df['date'])
df['year'] = df['date'].dt.year
multi_index = [df['year'].values,df['date'].dt.strftime('%b-%d').values]
fig = go.Figure()
fig.add_scatter(x=multi_index, y=df['GOOG'])
fig.show()
This question already has answers here:
Formatting datetime xlabels in matplotlib (pandas df.plot() method)
(5 answers)
Closed 10 months ago.
I have a problem when trying to plot a timeseries with matplotlib:
df = pd.read_csv('myfile.dat', skiprows=1)
#Change data type to datetime
date_format = '%Y-%m-%d %H:%M:%S'
df['TIME'] = pd.to_datetime(df['TIME'], format=date_format)
fig, ax = plt.subplots()
ax.plot(df['TIME'], df['Value'])
plt.show()
If I do:
print(df['TIME'][0])
the output is:
2022-04-16 14:32:00
which is the correct format! But when I plot everything, it changes to:
Can someone help me? I saw several times that you actually do not need Formatter and all that stuff.
Matplotlib finds the best format according to your date. For example if there were only data per each hour of a day, it would display just the hours, if data there were only a data per day during a span of a week, it would display just the days.
The solution I propose is with mdates.DateFormatter:
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
df = pd.read_csv('file.csv')
print (df)
#Change data type to datetime
date_format = '%Y-%m-%d %H:%M:%S'
df['TIME'] = pd.to_datetime(df['TIME'], format=date_format)
fig, ax = plt.subplots()
ax.plot(df['TIME'], df['Value'])
plt.xticks(rotation=45, ha='right')
ax.xaxis.set_major_formatter(mdates.DateFormatter("%Y-%m-%d %H:%M:%S"))
plt.show()
So I have a dataframe with a date column.
date
2021-06-17
2020-06-20
What I want to do is to do a scatterplot with the x-axis being the year, and the y-axis being month-day. So what I have already is this:
What I would like is for the y-axis ticks to be the actual month-day values and not the day number for the month-day-year. Not sure if this is possible, but any help is much appreciated.
Some Sample Data:
import pandas as pd
from matplotlib import pyplot as plt, dates as mdates
# Some Sample Data
df = pd.DataFrame({
'date': pd.date_range(
start='2000-01-01', end='2020-12-31', freq='D'
)
}).sample(n=100, random_state=5).sort_values('date').reset_index(drop=True)
Then one option would be to normalize the dates to the same year. Any year works as long as it's a leap year to handle the possibility of a February 29th (leap day).
This becomes the new y-axis.
# Create New Column with all dates normalized to same year
# Any year works as long as it's a leap year in case of a Feb-29
df['month-day'] = pd.to_datetime('2000-' + df['date'].dt.strftime('%m-%d'))
# Plot DataFrame
ax = df.plot(kind='scatter', x='date', y='month-day')
# Set Date Format On Axes
ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y')) # Year Only
ax.yaxis.set_major_formatter(mdates.DateFormatter('%m-%d')) # No Year
plt.tight_layout()
plt.show()
Problem: I am trying to make a very simple bar chart in Matplotlib of a Pandas DataFrame. The DateTime index is causing confusion, however: Matplotlib does not appear to understand the Pandas DateTime, and is labeling the years incorrectly. How can I fix this?
Code
# Make date time series
index_dates = pd.date_range('2018-01-01', '2021-01-01')
# Make data frame with some random data, using the date time index
df = pd.DataFrame(index=index_dates,
data = np.random.rand(len(index_dates)),
columns=['Data'])
# Make a bar chart in marplot lib
fig, ax = plt.subplots(figsize=(12,8))
df.plot.bar(ax=ax)
ax.xaxis.set_major_locator(mdates.YearLocator())
ax.xaxis.set_minor_locator(mdates.MonthLocator())
ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y'))
Instead of showing up as 2018-2021, however, the years show up as 1970 - 1973.
I've already looked at the answers here, here, and documentation here. I know the date timeindex is in fact a datetime index because when I call df.info() it shows it as a datetime index, and when I call index_dates[0].year it returns 2018. How can I fix this? Thank you!
The problem is with mixing df.plot.bar and matplotlib here.
df.plot.bar sets tick locations starting from 0 (and assigns labels), while matplotlib.dates expects the locations to be the number of days since 1970-01-01 (more info here).
If you do it with matplotlib directly, it shows labels correctly:
# Make a bar chart in marplot lib
fig, ax = plt.subplots(figsize=(12,8))
plt.bar(x=df.index, height=df['Data'])
ax.xaxis.set_major_locator(mdates.YearLocator())
ax.xaxis.set_minor_locator(mdates.MonthLocator())
ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y'))
Output:
I am plotting values from a dataframe where time is the x-axis. The time is formatted as 00:00 to 23:45. I only want to display the specific times 00:00, 06:00, 12:00, 18:00 on the x-axis of my plot. How can this be done? I have posted two figures, the first shows the format of my dataframe after setting the index to time. And the second shows my figure. Thank you for your help!
monday.set_index("Time", drop=True, inplace=True)
monday_figure = monday.plot(kind='line', legend = False,
title = 'Monday Average Power consumption')
monday_figure.xaxis.set_major_locator(plt.MaxNLocator(8))
Edit: Adding data as text:
Time,DayOfWeek,kW
00:00:00,Monday,5.8825
00:15:00,Monday,6.0425
00:30:00,Monday,6.0025
00:45:00,Monday,5.7475
01:00:00,Monday,6.11
01:15:00,Monday,5.8025
01:30:00,Monday,5.6375
01:45:00,Monday,5.85
02:00:00,Monday,5.7250000000000005
02:15:00,Monday,5.66
02:30:00,Monday,6.0025
02:45:00,Monday,5.71
03:00:00,Monday,5.7425
03:15:00,Monday,5.6925
03:30:00,Monday,5.9475
03:45:00,Monday,6.380000000000001
04:00:00,Monday,5.65
04:15:00,Monday,5.8725
04:30:00,Monday,5.865
04:45:00,Monday,5.71
05:00:00,Monday,5.6925
05:15:00,Monday,5.9975000000000005
05:30:00,Monday,5.905000000000001
05:45:00,Monday,5.93
06:00:00,Monday,5.6025
06:15:00,Monday,6.685
06:30:00,Monday,7.955
06:45:00,Monday,8.9225
07:00:00,Monday,10.135
07:15:00,Monday,12.9475
07:30:00,Monday,14.327499999999999
07:45:00,Monday,14.407499999999999
08:00:00,Monday,15.355
08:15:00,Monday,16.2175
08:30:00,Monday,18.355
08:45:00,Monday,18.902499999999996
09:00:00,Monday,19.0175
09:15:00,Monday,20.0025
09:30:00,Monday,20.355
09:45:00,Monday,20.3175
10:00:00,Monday,20.8025
10:15:00,Monday,20.765
10:30:00,Monday,21.07
10:45:00,Monday,19.9825
11:00:00,Monday,20.94
11:15:00,Monday,22.1325
11:30:00,Monday,20.6275
11:45:00,Monday,21.4475
12:00:00,Monday,22.092499999999998
The image above is produced using the code from the comment below.
Make sure you have a datetime index using pd.to_datetime when plotting timeseries.
I then used matplotlib.mdates to detect the desired ticks and format them in the plot. I don't know if it can be done from pandas with df.plot.
See matplotlib date tick labels. You can customize the HourLocator or use a different locator to suit your needs. Minor ticks are created the same way with ax.xaxis.set_minor_locator. Hope it helps.
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
# Using your dataframe
df = pd.read_clipboard(sep=',')
# Make sure you have a datetime index
df['Time'] = pd.to_datetime(df['Time'])
df = df.set_index('Time')
fig, ax = plt.subplots(1,1)
ax.plot(df['kW'])
# Use mdates to detect hours
locator = mdates.HourLocator(byhour=[0,6,12,18])
ax.xaxis.set_major_locator(locator)
# Format x ticks
formatter = mdates.DateFormatter('%H:%M:%S')
ax.xaxis.set_major_formatter(formatter)
# rotates and right aligns the x labels, and moves the bottom of the axes up to make room for them
fig.autofmt_xdate()