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:
Related
I want to plot Speed-Time graph and ı want to change to x label as 2012, 2013,2014,2015,2016 as like this
With this code ı got this graph:
Could you help me please. What should ı do ?
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
data=pd.read_excel("ts80.xlsx")
Date=data["Date"]
Speed=data["Speed"]
timestamp = pd.to_datetime(Date[0:]).dt.strftime("%Y%m%d")
fig, ax = plt.subplots(figsize=(13,6))
ax.plot(timestamp, Speed)
plt.xlabel("Time")
plt.ylabel("80Avg[m/s]")
plt.title("Mean Wind Speed at 80m")
ax.xaxis.set_minor_formatter(mdates.DateFormatter("%Y"))
plt.xticks([2012, 2013, 2014, 2015, 2016])
plt.show()
Could you please write correct code ?
The issue is that you're converting your dates strings to dates and then back to strings. Don't do that. Keep them as dates and then use the correct DataFormatter on your x-axis.
import numpy
from matplotlib import pyplot
from matplotlib import dates
import pandas
data = pd.read_excel("ts80.xlsx")
t = pd.to_datetime(data["Date"])
x = data["Speed"]
fig, ax = pyplot.subplots()
ax.plot(t, x)
ax.xaxis.set_major_formatter(dates.DateFormatter("%Y"))
ax.xaxis.set_major_locator(dates.YearLocator())
plt.show()
The reason why you want to use a proper Formatter and Locator is that it solves the general case where this code evolves into an interactive plot with a long series of data and the user can pan/zoom around. Hard-coded ticks or tick labels completely falls apart under that scenario.
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)
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()
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]))
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.