thanks to a LOT of help from overflowers I have FINALLY got formatted dates on my plot HOORAY!! BUT now there are too many of them! Can anyone see why please? I have only included the relevant list being plotted not the code.
here is the x_list
x_list [datetime.date(2015, 8, 4), datetime.date(2015, 8, 5), datetime.date(2015, 8, 6), datetime.date(2015, 8, 7)]
here's the format
ax.xaxis.set_major_formatter(mdates.DateFormatter('%m-%d'))
here's the plot
It would be easier to answer if you had included your code but I think this should fix it. You just need to specify what ticks should be included, using set_ticks():
import matplotlib.dates as mdates
import matplotlib.pyplot as plt
import datetime
x_list = [datetime.date(2015, 8, 4), datetime.date(2015, 8, 5), datetime.date(2015, 8, 6), datetime.date(2015, 8, 7)]
y = [5, 7, 3, 9] # just an example
fig = plt.figure()
ax = fig.add_subplot(111)
ax.xaxis.set_major_formatter(mdates.DateFormatter('%m-%d'))
ax.plot(x_list, y)
ax.xaxis.set_ticks(x_list)
plt.show()
Related
I have dataframe x2 with two columns. i am trying to plot but didnt get xticks.
data:
bins pp
0 (0, 1] 0.155463
1 (1, 2] 1.528947
2 (2, 3] 2.436064
3 (3, 4] 3.507811
4 (4, 5] 4.377849
5 (5, 6] 5.538044
6 (6, 7] 6.577340
7 (7, 8] 7.510983
8 (8, 9] 8.520378
9 (9, 10] 9.721899
i tried this code result is fine just cant find x-axis ticks just blank. i want bins column value should be on x-axis
x2.plot(x='bins',y=['pp'])
x2.dtypes
Out[141]:
bins category
pp float64
The following is to show that this problem should not occur with pandas 0.24.1 or higher.
import numpy as np
import pandas as pd
print(pd.__version__) # prints 0.24.2
import matplotlib.pyplot as plt
df = pd.DataFrame({"Age" : np.random.rayleigh(30, size=300)})
s = pd.cut(df["Age"], bins=np.arange(0,91,10)).value_counts().to_frame().sort_index().reset_index()
s.plot(x='index',y="Age")
plt.show()
results in
I want to specify manually the color of a line segment in holoviews, based on a third column.
I'm aware of the hv.Path examples, however, this reduces the length of the line with 1 segment, which I don't want.
I can do it using bokeh, or using matplotlib, but I can't get it right using holoviews
def get_color(min_val, max_val, val, palette):
return palette[(int((val-min_val)*((len(palette)-1)/(max_val-min_val))+.5))]
from bokeh.io import output_file, show
from bokeh.plotting import figure
y = [0,1,2,3,4,5]
x = [0]*len(y)
z = [1,2,3,4,5]
p = figure(plot_width=500, plot_height=200, tools='')
[p.line([x[i],x[i+1]],[y[i],y[i+1]],line_color = get_color(1,5,z,Viridis256), line_width=4) for i,z in enumerate(z) ]
show(p)
import numpy
import matplotlib.pyplot as plt
from matplotlib.collections import LineCollection
# The line format you curently have:
lines = [[(0, 1, 2, 3, 4), (4, 5, 6, 7, 8)],
[(0, 1, 2, 3, 4), (0, 1, 2, 3, 4)],
[(0, 1, 2, 3, 4), (8, 7, 6, 5, 4)],
[(4, 5, 6, 7, 8), (0, 1, 2, 3, 4)]]
# Reformat it to what `LineCollection` expects:
lines = [zip(x, y) for x, y in lines]
z = np.array([0.1, 9.4, 3.8, 2.0])
fig, ax = plt.subplots()
lines = LineCollection(lines, array=z, cmap=plt.cm.rainbow, linewidths=5)
ax.add_collection(lines)
fig.colorbar(lines)
# Manually adding artists doesn't rescale the plot, so we need to autoscale
ax.autoscale()
plt.show()
from bokeh.io import output_file, show
from bokeh.plotting import figure
y = [0,1,2,3,4,5]
x = [0]*len(y)
z = [1,2,3,4,5]
p = figure(plot_width=500, plot_height=200, tools='')
[p.line([x[i],x[i+1]],[y[i],y[i+1]],line_color = get_color(1,5,z,Viridis256), line_width=4) for i,z in enumerate(z) ]
show(p)
from bokeh.palettes import Viridis256
curvlst = [hv.Curve([[x[i],y[i]],[x[i+1],y[i+1]]],line_color = get_color(1,5,z,Viridis256)) for i,z in enumerate(z) ]
hv.Overlay(curvlst)
WARNING:param.Curve26666: Setting non-parameter attribute line_color=#440154 using a mechanism intended only for parameters
You could use a so called dim transform by rewriting the function a little bit:
def get_color(val, min_val, max_val, palette):
return [palette[(int((val-min_val)*((len(palette)-1)/(max_val-min_val))+.5))]]
y = [0,1,2,3,4,5]
x = [0]*len(y)
z = [1,2,3,4,5]
hv.NdOverlay({z: hv.Curve(([x[i],x[i+1]], [y[i],y[i+1]])) for i, z in enumerate(z)}, kdims=['z']).opts(
'Curve', color=hv.dim('z', get_color, 1, 5, Viridis256))
That being said, I don't think you should have to manually colormap Curves so I've opened: https://github.com/pyviz/holoviews/issues/3764.
I think I found out..
from bokeh.palettes import Viridis256
def get_color(min_val, max_val, val, palette):
return palette[(int((val-min_val)*((len(palette)-1)/(max_val-min_val))+.5))]
curvlst = [hv.Curve([[x[i],y[i]],[x[i+1],y[i+1]]]).opts(color=get_color(1,5,z,Viridis256)) for i,z in enumerate(z) ]
hv.Overlay(curvlst)
Please let me know it this is good practise, or if you know a better way..
I have set the following xlim on my x axis:
axA.set_xlim(datetime.date(2016, 12, 1), datetime.date(2018, 1, 30))
and now I would like to get the position of the 12th of October (2017-10-12) on my X axis, so that I can then put an annotation there.
I tried to figure that out the using date2num and datestr2num:
release_date = datetime.datetime(2017, 10, 12)
print(mdates.date2num(release_date))
print(mdates.datestr2num('2017-10-12'))
print(axA.get_xlim())
The above code output:
-736614.0
736614.0
(17136.0, 17561.0)
First it seems like date2num and datestr2num don't give an identical result, but more problematically, those results are not within the range of xlim.
How can I find the X position of a date (to place an annotation), given the xlim I set above?
Code to reproduce the problem:
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
from datetime import datetime
def get_dataframe():
values = [12, 16, 20]
dates = [
datetime(2017, 12, 24),
datetime(2017, 12, 23),
datetime(2017, 12, 22)
]
df = pd.DataFrame(data={'date': dates, 'value': values})
df = df.set_index(['date']).sort_index()
return df
def plot(dataA):
fig, axA = plt.subplots()
dataA.plot(ax=axA)
axA.set_xlim(datetime(2016, 12, 1), datetime(2018, 1, 30))
release = datetime(2017, 10, 12)
print(mdates.date2num(release))
print(mdates.datestr2num('2017-10-12'))
print(axA.get_xlim())
df = get_dataframe()
plot(df)
plt.show()
You can use a date object directly if you have a date xaxis:
ax.annotate('hello', xy=(datetime.datetime(2017, 10, 12), 1),
xytext=(datetime.datetime(2017, 10, 12), 5),
arrowprops={'facecolor': 'r'})
I have the following data frame my_df:
my_1 my_2 my_3
--------------------------------
0 5 7 4
1 3 5 13
2 1 2 8
3 12 9 9
4 6 1 2
I want to make a plot where x-axis is categorical values with my_1, my_2, and my_3. y-axis is integer. For each column in my_df, I want to plot all its 5 values at x = my_i. What kind of plot should I use in matplotlib? Thanks!
You could make a bar chart:
import pandas as pd
import matplotlib.pyplot as plt
df = pd.DataFrame({'my_1': [5, 3, 1, 12, 6], 'my_2': [7, 5, 2, 9, 1], 'my_3': [4, 13, 8, 9, 2]})
df.T.plot(kind='bar')
plt.show()
or a scatter plot:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
df = pd.DataFrame({'my_1': [5, 3, 1, 12, 6], 'my_2': [7, 5, 2, 9, 1], 'my_3': [4, 13, 8, 9, 2]})
fig, ax = plt.subplots()
cols = np.arange(len(df.columns))
x = np.repeat(cols, len(df))
y = df.values.ravel(order='F')
color = np.tile(np.arange(len(df)), len(df.columns))
scatter = ax.scatter(x, y, s=150, c=color)
ax.set_xticks(cols)
ax.set_xticklabels(df.columns)
cbar = plt.colorbar(scatter)
cbar.set_ticks(np.arange(len(df)))
plt.show()
Just for fun, here is how to make the same scatter plot using Pandas' df.plot:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
df = pd.DataFrame({'my_1': [5, 3, 1, 12, 6], 'my_2': [7, 5, 2, 9, 1], 'my_3': [4, 13, 8, 9, 2]})
columns = df.columns
index = df.index
df = df.stack()
df.index.names = ['color', 'column']
df = df.rename('y').reset_index()
df['x'] = pd.Categorical(df['column']).codes
ax = df.plot(kind='scatter', x='x', y='y', c='color', colorbar=True,
cmap='viridis', s=150)
ax.set_xticks(np.arange(len(columns)))
ax.set_xticklabels(columns)
cbar = ax.collections[-1].colorbar
cbar.set_ticks(index)
plt.show()
Unfortunately, it requires quite a bit of DataFrame manipulation just to call
df.plot and then there are some extra matplotlib calls needed to set the tick
marks on the scatter plot and colorbar. Since Pandas is not saving effort here,
I would go with the first (NumPy/matplotlib) approach shown above.
I want to have a scatter plot with ticks as marginals:
x = [ 0, 1, 1.2, 1.3, 4, 5, 6, 7, 8.2, 9, 10]
y = [.2, .4, 2, 3, 4, 5, 5.1, 5.2, 4, 3, 8]
fig, ax1 = plt.subplots()
for spine in ax1.spines.values():
spine.set_visible(False)
ax1.scatter(x, y)
ax1.set_xticks(x)
ax1.set_xticklabels([])
ax1.set_yticks(y)
ax1.set_yticklabels([])
And on top of that, I want to have ticklabels at other positions, not determined by the ticks:
xticklabels = [0, 5, 10]
yticklabels = xticklabels
How could I possibly achieve that?
Matplotlib axes have major and minor ticks. You may use the minor ticks to show the marginal locations of the points. You may turn the major ticks off but show the ticklabels for them.
To set ticks at certain positions you can use a FixedLocator. To change the appearance of the ticks or turn them off, the axes has a tick_params method.
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
x = [ 0, 1, 1.2, 1.3, 4, 5, 6, 7, 8.2, 9, 10]
y = [.2, .4, 2, 3, 4, 5, 5.1, 5.2, 4, 3, 8]
xticklabels = [0, 5, 10]
yticklabels = xticklabels
fig, ax = plt.subplots()
for spine in ax.spines.values():
spine.set_visible(False)
ax.scatter(x, y)
ax.xaxis.set_major_locator(ticker.FixedLocator(xticklabels))
ax.yaxis.set_major_locator(ticker.FixedLocator(yticklabels))
ax.xaxis.set_minor_locator(ticker.FixedLocator(x))
ax.yaxis.set_minor_locator(ticker.FixedLocator(y))
ax.tick_params(axis="both", which="major", bottom="off", left="off")
ax.tick_params(axis="both", which="minor", length=4)
plt.show()
Note that I personally find this plot rather difficult to grasp and if I may, I would propose something more like this:
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
x = [ 0, 1, 1.2, 1.3, 4, 5, 6, 7, 8.2, 9, 10]
y = [.2, .4, 2, 3, 4, 5, 5.1, 5.2, 4, 3, 8]
xticklabels = [0, 5, 10]
yticklabels = xticklabels
fig, ax = plt.subplots()
ax.scatter(x, y)
ax.xaxis.set_minor_locator(ticker.FixedLocator(x))
ax.yaxis.set_minor_locator(ticker.FixedLocator(y))
c = "#aaaaaa"
ax.tick_params(axis="both", which="major", direction="out", color=c)
ax.tick_params(axis="both", which="minor", length=6, direction="in",
color="C0", width=1.5)
plt.setp(ax.spines.values(), color=c)
plt.setp(ax.get_xticklabels(), color=c)
plt.setp(ax.get_yticklabels(), color=c)
plt.show()