Reformat seaborn axis tick labels (datetime and scientific notation) - python

I am trying to plot a bar chart. However, the number on x-axis shows 0.0, 0.5, 1.0 and y-axis shows the np datetime.
I want the x-axis shows the exactly number and y-axis shows the date with dd-mm-yy only. May I know how can I solve it?
from pandas_datareader import data
import datetime
dateToday = datetime.datetime.today().strftime("%Y-%m-%d")
# Only get the adjusted close.
tickers = data.DataReader(['NFLX'],
start='',
end=dateToday,
data_source='yahoo')['Volume'][-50:]
import matplotlib.pyplot as plt
%matplotlib inline
import seaborn as sns
# Change the style of the figure to the "dark" theme
sns.set_style("darkgrid")
plt.figure(figsize=(12,6))
plt.title('Returns')
sns.barplot(y=tickers.index,x=tickers['NFLX'],color='b',edgecolor='w',label='7d_returns',orient = 'h')
plt.xticks(rotation = 0)

For the date formatting, you can supply a formatted index: y=tickers.index.strftime('%d-%m-%Y')
For the x axis, they are currently in scientific notation (note the 1e7 in the bottom right corner), so you can disable the scientific notation: plt.ticklabel_format(style='plain', axis='x')
sns.barplot(y=tickers.index.strftime('%d-%m-%Y'), x=tickers['NFLX'], color='b', edgecolor='w', label='7d_returns', orient='h')
plt.ticklabel_format(style='plain', axis='x')

Related

Matplotlib - How I can define the x-axis with different intervals like the next picture? I would like to open certain intervals

I would like to create a similar graph, in this case China and USA have huge PIB that I cant see the details for small countries
For this, you can use ax.set_xscale:
import matplotlib.pyplot as plt
from matplotlib.ticker import ScalarFormatter
plt.scatter(your_data)
ax = plt.gca() #get current axis object
ax.set_xscale('log') #you can use 'symlog' if your data is close to 0
ax.set_yscale('log')
#if you don't want to show the ticks in scientific notation
for axis in [ax.xaxis, ax.yaxis]:
formatter = ScalarFormatter()
formatter.set_scientific(False)
axis.set_major_formatter(formatter)

Matplotlib - uneven intervals between x-axis with datetime

I am currently experiencing an issue where the spaces between ticks on my plot appear to have uneven intervals when using a DatetimeIndex for my x-axis. The code is as follows:
x = pd.date_range('2018-11-03', '2018-12-30')
plt.plot(x, np.arange(len(x)))
plt.xticks(rotation=45)
Note the two instances in which the dates do not increment by the typical 7-day period. Even after extending the time period, the issue persists:
x = pd.date_range('2018-11-03', '2019-03-20')
plt.plot(x, np.arange(len(x)))
plt.xticks(rotation=45)
How can I override this behavior to have standard 7-day intervals on my plot? Thank you.
You can use matplotlib's ticker module to customize tick locations:
import matplotlib.pyplot as plt
import pandas as pd
import matplotlib.ticker as ticker
x = pd.date_range('2018-11-03', '2019-03-20')
plt.plot(x, np.arange(len(x)))
plt.xticks(rotation=45)
ax=plt.gca()
ax.xaxis.set_major_locator(ticker.MultipleLocator(7))
The above script returns the following image:

Axis interval spacing when plotting with pandas timedelta

I'm trying to plot some columns in a dataframe that has pandas timedelta values as its index. When I plot it, all the points are evenly spaced along the x axis even if there's a variable time between.
time = [pd.Timestamp('9/3/2016')-pd.Timestamp('9/1/2016'),pd.Timestamp('9/8/2016')-pd.Timestamp('9/1/2016'),pd.Timestam\p('9/29/2016')-pd.Timestamp('9/1/2016')]
df = pd.DataFrame(index=time, columns=['y'],data=[5,0,10])
df.plot()
plt.show()
Wrong spacing
If instead I used dates instead of timedelta, I get the proper spacing on the x axis:
time = [pd.Timestamp('9/3/2016'),pd.Timestamp('9/5/2016'),pd.Timestamp('9/20/2016')]
df = pd.DataFrame(index=time, columns=['y'],data=[5,0,10])
df.plot()
plt.show()
Right spacing
Is there a way to get this to display correctly?
At the moment, it's not fully supported yet in pandas. Please see this issue on Github for more info.
For a quick workaround, you can use:
import matplotlib.pyplot as plt
plt.plot(df.index, df.values)
Here's an example of how you could play with the ticks to make them readable (rather than just a very large number)
import matplotlib as mpl
import datetime
fig, ax = plt.subplots()
ax.plot(df.index, df.values)
plt.xticks([t.value for t in df.index], df.index, rotation=45)
plt.show()

how to round date format on x axis in matplotlib

I am trying to plot a curve in between two others filled and as soon as I have these two "plots", my x-axis become strange.
Here is my MWE:
import matplotlib.pyplot as plt
from matplotlib import dates as mdates
import datetime
import numpy as np
dates=[u'0600', u'0630', u'0700', u'0730', u'0800', u'0830', u'0900', u'0930', u'1000', u'1030']#["0800","0830","0900"]
x=[datetime.datetime.strptime(h,'%H%M') for h in dates]
y=np.arange(len(x))
tmin=y/2.
tmax=y*2.
fig, ax = plt.subplots()
ax.plot(x,y,'r')
ax.fill_between(x,tmin,tmax)
hfmt = mdates.DateFormatter('%H:%M')
ax.xaxis.set_major_formatter(hfmt)
fig.autofmt_xdate()
plt.savefig('plot.png')
plt.show()
where the x-axis should looks like
which can easily be obtained by commenting one of the plot or fill_between command line.
Any idea of how to have the second x-axis in the first figure ?
The easiest way would probably be to use
ax.x_axis.set_major_locator(mdates.MinuteLocator(byminute=[0,30]))

Seaborn/Matplotlib Date Axis barplot minor-major tick formatting

I'm building a Seaborn barplot. The x-axis are dates, and the y-axis are integers.
I'd like to format major/minor ticks for the dates. I'd like Mondays' ticks to be bold and a different color (ie, "major ticks"), with the rest of the week less bold.
I have not been able to get major and minor tick formatting on the x-axis to work with Seaborn barplots. I'm stumped, and thus turning here for help.
I'm starting with the stackoverflow example that answered this question: Pandas timeseries plot setting x-axis major and minor ticks and labels
If I do a simple modification it to use a Seaborn barplot and I lose my X-axis ticks:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.dates as dates
import seaborn as sns
idx = pd.date_range('2011-05-01', '2011-07-01')
s = pd.Series(np.random.randn(len(idx)), index=idx)
###########################################
## Swap out these two lines of code:
#fig, ax = plt.subplots()
#ax.plot_date(idx.to_pydatetime(), s, 'v-')
## with this one
ax = sns.barplot(idx.to_pydatetime(), s)
###########################################
ax.xaxis.set_minor_locator(dates.WeekdayLocator(byweekday=(1),
interval=1))
ax.xaxis.set_minor_formatter(dates.DateFormatter('%d\n%a'))
ax.xaxis.grid(True, which="minor")
ax.yaxis.grid()
ax.xaxis.set_major_locator(dates.MonthLocator())
ax.xaxis.set_major_formatter(dates.DateFormatter('\n\n\n%b\n%Y'))
plt.tight_layout()
## save the result to a png instead of plotting to screen:
myFigure = plt.gcf()
myFigure.autofmt_xdate()
myFigure.set_size_inches(11,3.8)
plt.title('Example Chart', loc='center')
plt.savefig('/tmp/chartexample.png', format='png', bbox_inches='tight')
I've tried a variety of approaches but something in Seaborn seems to be overriding or undoing any attempts at major and minor axis formatting that I've managed to cook up yet beyond some simple styling for all ticks when I use set_xticklabels().
I can sort of get formatting on just the major ticks by using MultipleLocator(), but I can't get any formatting on the minor ticks.
I've also experimented with myFigure.autofmt_xdate() to see if it would help, but it doesn't seem to like mixed major & minor ticks on the same axis either.
I came across this while trying to solve the same problem. Based on the useful pointer from #mwaskom (that categorical plots like boxplots lose their structure and just become date-named categories) and ended up doing the location and formatting in Python as so:
from datetime import datetime
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.dates as dates
import seaborn as sns
idx = pd.date_range('2011-05-01', '2011-07-01')
s = pd.Series(np.random.randn(len(idx)), index=idx)
fig, ax = plt.subplots(figsize = (12,6))
ax = sns.barplot(idx.to_pydatetime(), s, ax = ax)
major_ticks = []
major_tick_labels = []
minor_ticks = []
minor_tick_labels = []
for loc, label in zip(ax.get_xticks(), ax.get_xticklabels()):
when = datetime.strptime(label.get_text(), '%Y-%m-%d %H:%M:%S')
if when.day == 1:
major_ticks.append(loc)
major_tick_labels.append(when.strftime("\n\n\n%b\n%Y"))
else:
minor_ticks.append(loc)
if when.weekday() == 0:
minor_tick_labels.append(when.strftime("%d\n%a"))
else:
minor_tick_labels.append(when.strftime("%d"))
ax.set_xticks(major_ticks)
ax.set_xticklabels(major_tick_labels)
ax.set_xticks(minor_ticks, minor=True)
ax.set_xticklabels(minor_tick_labels, minor=True)
Of course, you don't have to set the ticks based on parsing the labels which were installed from the data, if it's easier to start with the source data and just keep the indices aligned, but I prefer to have a single source of truth.
You can also mess with font weight, rotation, etc, on individual labels by getting the Text objects for the relevant label and calling set_ methods on it.

Categories

Resources