Add limit orders on side of the chart Plotly - python
Trying to add limit order on right side that will show where limit orders was places and volume of that limit. if it sell order make it red and if buy green. If volume of limit order is big make line bigger. There is quick example what I'm looking for.
Here is full code that I have with chart data: https://textbin.net/noz678jlue
chartData = {'Price': [0.965879, 0.964773, 0.96447, 0.961223, 0.958788, 0.956747, 0.958788, 0.959872, 0.959868, 0.960104, 0.961375, 0.962256, 0.963297, 0.963315, 0.964611, 0.964513, 0.963761, 0.963763, 0.963922, 0.963907, 0.963857, 0.963265, 0.963293, 0.963171, 0.96318, 0.963707, 0.964389, 0.964352, 0.963077, 0.961785, 0.959572, 0.958703, 0.959223, 0.95819, 0.952994, 0.95124, 0.950693, 0.950906, 0.95184, 0.951838, 1.053997, 1.060501, 1.060672, 1.060486, 1.060171, 1.060241, 1.059292, 1.059263, 1.059205, 0.95906, 0.954787, 0.954901, 0.954993, 0.955447, 0.955465, 0.955626, 0.953638, 0.952751, 0.951972, 0.950729, 0.950532, 0.952849, 0.952773, 0.952682, 0.952351, 0.948383, 0.94847, 0.948451, 0.95198, 0.952234, 0.951982, 0.952163, 0.952301, 0.952407, 0.955843, 0.956628, 0.957734, 0.957548, 0.95771, 0.956813, 0.958674, 0.958295, 0.954697, 0.953861, 0.955926, 0.953264, 0.951443, 0.950245, 0.949453, 0.949492, 0.948764, 0.946932, 0.949487, 0.950302, 0.950381, 0.949979, 0.948601, 0.949252, 0.949217, 0.949271, 0.947859, 0.947683, 0.947763, 0.947593, 0.948247, 0.9483, 0.948568, 0.947236, 0.946515, 0.946128, 0.946793, 0.946244, 0.951683, 0.951324, 0.950662, 0.949001, 0.947648, 0.946191, 0.946928, 0.933038, 0.92239, 0.923197, 0.925719, 0.937193, 0.93354, 0.932933, 0.932073, 0.931954, 0.932393, 0.931602, 0.932908, 0.932966, 0.933866, 0.931223, 0.929834, 0.933195, 0.936534, 0.935959, 0.932762, 0.931187, 0.937434, 0.937664, 0.936378, 0.934742, 0.934742], 'Date': [1652117700000, 1652118000000, 1652118300000, 1652118600000, 1652118900000, 1652119200000, 1652119500000, 1652119800000, 1652120100000, 1652120400000, 1652120700000, 1652121000000, 1652121300000, 1652121600000, 1652121900000, 1652122200000, 1652122500000, 1652122800000, 1652123100000, 1652123400000, 1652123700000, 1652124000000, 1652124300000, 1652124600000, 1652124900000, 1652125200000, 1652125500000, 1652125800000, 1652126100000, 1652126400000, 1652126700000, 1652127000000, 1652127300000, 1652127600000, 1652127900000, 1652128200000, 1652128500000, 1652128800000, 1652129100000, 1652129400000, 1652129700000, 1652130000000, 1652130300000, 1652130600000, 1652130900000, 1652131200000, 1652131500000, 1652131800000, 1652132100000, 1652132400000, 1652132700000, 1652133000000, 1652133300000, 1652133600000, 1652133900000, 1652134200000, 1652134500000, 1652134800000, 1652135100000, 1652135400000, 1652135700000, 1652136000000, 1652136300000, 1652136600000, 1652136900000, 1652137200000, 1652137500000, 1652137800000, 1652138100000, 1652138400000, 1652138700000, 1652139000000, 1652139300000, 1652139600000, 1652139900000, 1652140200000, 1652140500000, 1652140800000, 1652141100000, 1652141400000, 1652141700000, 1652142000000, 1652142300000, 1652142600000, 1652142900000, 1652143200000, 1652143500000, 1652143800000, 1652144100000, 1652144400000, 1652144700000, 1652145000000, 1652145300000, 1652145600000, 1652145900000, 1652146200000, 1652146500000, 1652146800000, 1652147100000, 1652147400000, 1652147700000, 1652148000000, 1652148300000, 1652148600000, 1652148900000, 1652149200000, 1652149500000, 1652149800000, 1652150100000, 1652150400000, 1652150700000, 1652151000000, 1652151300000, 1652151600000, 1652151900000, 1652152200000, 1652152500000, 1652152800000, 1652153100000, 1652153400000, 1652153700000, 1652154000000, 1652154300000, 1652154600000, 1652154900000, 1652155200000, 1652155500000, 1652155800000, 1652156100000, 1652156400000, 1652156700000, 1652157000000, 1652157300000, 1652157600000, 1652157900000, 1652158200000, 1652158500000, 1652158800000, 1652159100000, 1652159400000, 1652159700000, 1652160000000, 1652160300000, 1652160600000, 1652160636000]}
limitOrders = {"BUY":{"0.98": 50000, "0.93": 5555, "0.67": 300000, "0.85": 5555, "0.47": 300000, '0.57': 300000, "0.95": 5555}, "SELL":{"1.00": 50000, "0.83": 5555, "0.67": 300000, "0.75": 5555, "0.57": 300000, '0.67': 300000, "0.85": 5555}}
eastern = pytz.timezone('US/Eastern')
df: DataFrame = pd.DataFrame.from_dict(chatData).fillna(method="backfill")
df['Date'] = pd.to_datetime(df['Date'], unit='ms').dt.tz_localize('UTC').dt.tz_convert(eastern)
x = df['Date']
y = df['Price']
layout = Layout(
autosize=True,
width=1980,
height=1080,
margin=dict(l=10, r=10, t=80, b=10),
title="<b>TEST</b>",
paper_bgcolor='rgb(0.03,0.00,0.07)',
plot_bgcolor='rgb(0.03,0.00,0.07)',
yaxis_tickformat=".3f",
title_x=0.5,
font=dict(
family="Amarante,cursive",
size=25,
color="White")
)
fig = go.Figure([
go.Scatter(x=x, y=1.01 * np.ones_like(y), opacity=0.5, line_width=0, showlegend=False),
go.Scatter(x=x, y=y, fill='tonexty', fillcolor="#240050", line=dict(color="#940099"), line_shape='spline',
opacity=0, showlegend=False)
], layout=layout)
fig.show()
You can use plotly shapes to place down the line segments representing limit orders, and annotations to place down the text with the corresponding volume amount. However, you will need to increase the right margin so the annotations are visible.
import pytz
import numpy as np
import pandas as pd
import plotly.graph_objects as go
chartData = {'Price': [0.965879, 0.964773, 0.96447, 0.961223, 0.958788, 0.956747, 0.958788, 0.959872, 0.959868, 0.960104, 0.961375, 0.962256, 0.963297, 0.963315, 0.964611, 0.964513, 0.963761, 0.963763, 0.963922, 0.963907, 0.963857, 0.963265, 0.963293, 0.963171, 0.96318, 0.963707, 0.964389, 0.964352, 0.963077, 0.961785, 0.959572, 0.958703, 0.959223, 0.95819, 0.952994, 0.95124, 0.950693, 0.950906, 0.95184, 0.951838, 1.053997, 1.060501, 1.060672, 1.060486, 1.060171, 1.060241, 1.059292, 1.059263, 1.059205, 0.95906, 0.954787, 0.954901, 0.954993, 0.955447, 0.955465, 0.955626, 0.953638, 0.952751, 0.951972, 0.950729, 0.950532, 0.952849, 0.952773, 0.952682, 0.952351, 0.948383, 0.94847, 0.948451, 0.95198, 0.952234, 0.951982, 0.952163, 0.952301, 0.952407, 0.955843, 0.956628, 0.957734, 0.957548, 0.95771, 0.956813, 0.958674, 0.958295, 0.954697, 0.953861, 0.955926, 0.953264, 0.951443, 0.950245, 0.949453, 0.949492, 0.948764, 0.946932, 0.949487, 0.950302, 0.950381, 0.949979, 0.948601, 0.949252, 0.949217, 0.949271, 0.947859, 0.947683, 0.947763, 0.947593, 0.948247, 0.9483, 0.948568, 0.947236, 0.946515, 0.946128, 0.946793, 0.946244, 0.951683, 0.951324, 0.950662, 0.949001, 0.947648, 0.946191, 0.946928, 0.933038, 0.92239, 0.923197, 0.925719, 0.937193, 0.93354, 0.932933, 0.932073, 0.931954, 0.932393, 0.931602, 0.932908, 0.932966, 0.933866, 0.931223, 0.929834, 0.933195, 0.936534, 0.935959, 0.932762, 0.931187, 0.937434, 0.937664, 0.936378, 0.934742, 0.934742], 'Date': [1652117700000, 1652118000000, 1652118300000, 1652118600000, 1652118900000, 1652119200000, 1652119500000, 1652119800000, 1652120100000, 1652120400000, 1652120700000, 1652121000000, 1652121300000, 1652121600000, 1652121900000, 1652122200000, 1652122500000, 1652122800000, 1652123100000, 1652123400000, 1652123700000, 1652124000000, 1652124300000, 1652124600000, 1652124900000, 1652125200000, 1652125500000, 1652125800000, 1652126100000, 1652126400000, 1652126700000, 1652127000000, 1652127300000, 1652127600000, 1652127900000, 1652128200000, 1652128500000, 1652128800000, 1652129100000, 1652129400000, 1652129700000, 1652130000000, 1652130300000, 1652130600000, 1652130900000, 1652131200000, 1652131500000, 1652131800000, 1652132100000, 1652132400000, 1652132700000, 1652133000000, 1652133300000, 1652133600000, 1652133900000, 1652134200000, 1652134500000, 1652134800000, 1652135100000, 1652135400000, 1652135700000, 1652136000000, 1652136300000, 1652136600000, 1652136900000, 1652137200000, 1652137500000, 1652137800000, 1652138100000, 1652138400000, 1652138700000, 1652139000000, 1652139300000, 1652139600000, 1652139900000, 1652140200000, 1652140500000, 1652140800000, 1652141100000, 1652141400000, 1652141700000, 1652142000000, 1652142300000, 1652142600000, 1652142900000, 1652143200000, 1652143500000, 1652143800000, 1652144100000, 1652144400000, 1652144700000, 1652145000000, 1652145300000, 1652145600000, 1652145900000, 1652146200000, 1652146500000, 1652146800000, 1652147100000, 1652147400000, 1652147700000, 1652148000000, 1652148300000, 1652148600000, 1652148900000, 1652149200000, 1652149500000, 1652149800000, 1652150100000, 1652150400000, 1652150700000, 1652151000000, 1652151300000, 1652151600000, 1652151900000, 1652152200000, 1652152500000, 1652152800000, 1652153100000, 1652153400000, 1652153700000, 1652154000000, 1652154300000, 1652154600000, 1652154900000, 1652155200000, 1652155500000, 1652155800000, 1652156100000, 1652156400000, 1652156700000, 1652157000000, 1652157300000, 1652157600000, 1652157900000, 1652158200000, 1652158500000, 1652158800000, 1652159100000, 1652159400000, 1652159700000, 1652160000000, 1652160300000, 1652160600000, 1652160636000]}
limitOrders = {"BUY":{"0.98": 50000, "0.93": 5555, "0.67": 300000, "0.85": 5555, "0.47": 300000, '0.57': 300000, "0.95": 5555}, "SELL":{"1.00": 50000, "0.83": 5555, "0.67": 300000, "0.75": 5555, "0.57": 300000, '0.67': 300000, "0.85": 5555}}
eastern = pytz.timezone('US/Eastern')
df = pd.DataFrame.from_dict(chartData).fillna(method="backfill")
df['Date'] = pd.to_datetime(df['Date'], unit='ms').dt.tz_localize('UTC').dt.tz_convert(eastern)
x = df['Date']
y = df['Price']
layout = dict(
autosize=True,
width=1980,
height=1080,
margin=dict(l=10, r=200, t=80, b=10),
title="<b>TEST</b>",
paper_bgcolor='rgb(0.03,0.00,0.07)',
plot_bgcolor='rgb(0.03,0.00,0.07)',
yaxis_tickformat=".3f",
title_x=0.5,
font=dict(
family="Amarante,cursive",
size=25,
color="White")
)
fig = go.Figure([
go.Scatter(x=x, y=1.01 * np.ones_like(y), opacity=0.5, line_width=0, showlegend=False),
go.Scatter(x=x, y=y, fill='tonexty', fillcolor="#240050", line=dict(color="#940099"), line_shape='spline',
opacity=0, showlegend=False)
], layout=layout)
## add limit orders using annotations
## use paper coordinates to determine length in the x direction
max_limit_volume = 500000
max_limit_volume_length = 0.25
for limit_order_name,limit_order_info in limitOrders.items():
if limit_order_name == "BUY":
for y_value, volume in limit_order_info.items():
y_value = float(y_value)
fig.add_shape(type="line",
x0=1, y0=y_value, x1=1-0.1*volume/max_limit_volume, y1=y_value,
line=dict(color="green",width=3)
)
fig.add_annotation(
x=1.05, y=y_value,
yshift=-30, xref="paper",
text=f"${volume}", font=dict(color="white")
)
if limit_order_name == "SELL":
for y_value, volume in limit_order_info.items():
y_value = float(y_value)
fig.add_shape(type="line",
x0=1, y0=y_value, x1=1-0.1*volume/max_limit_volume, y1=y_value,
line=dict(color="red",width=3)
)
fig.add_annotation(
x=1.05, y=y_value,
yshift=-30e, xref="paper",
text=f"${volume}", font=dict(color="white")
)
fig.update_shapes(dict(xref='paper', yref='y'))
fig.show()
Related
How to add images to each row in a Plotly Table?
I would like to add images to the rows in a Plotly Table, but could not find a good solution. As an alternative option, I am using the method add_layout_image() placing the images approximately at the row space - see the example of what I am trying to achieve. Anyone has a better solution!? import plotly.graph_objects as go import pandas as pd import base64 data = {'team': {1: 'Sales team 1', 2: 'Sales team 2', 3: 'Sales team 3'}, 'award': {1: '', 2: '', 3: ''}, 'performance': {1: '67.00%', 2: '45.00%', 3: '35.00%'}} df = pd.DataFrame(data) fig = go.Figure(data=[go.Table( columnwidth=[40, 40, 40], header=dict( values=list(df.columns), height=35), cells=dict( values=[df.team, df.award, df.performance], align=['center', 'center', 'center'], font=dict(color='black', size=18), height=45) )]) heightRow = fig.data[0].cells.height numberRow = fig.data[0].cells.values[0].__len__() image_1st = 'medal1st.png' image_1st_base64 = base64.b64encode(open(image_1st, 'rb').read()) step_y = 1 / numberRow * .2 coordinate_y = 0 for index, eachRow in enumerate(df.iterrows()): fig.add_layout_image( source='data:image/png;base64,{}'.format(image_1st_base64.decode()), x=0.5, y=.9 - coordinate_y, xref="x domain", yref="y domain", xanchor="center", yanchor="bottom", sizex=.055, sizey=.055, ) coordinate_y = coordinate_y + step_y fig.show()
negative dimensions are not allowed in GIS
I define coordinates for cities, it worked for one city, but not for others almaty = df.loc[(df['latitude']>= 43.117971)&(df['latitude'] <= 51.21465 )& (df['longitude']>= 76.3)&(df['longitude']<= 77.017043)] astana = df.loc[(df['latitude']>=43.67 )&(df['latitude'] <= 49.33 )& (df['longitude']>=71.4 )&(df['longitude']<=71.7 )] shymkent = df.loc[(df['latitude']>= 43.3006564195014)&(df['latitude'] <=43.393584 )& (df['longitude']>=69.521168 )&(df['longitude']<=69.796007 )] karaganda = df.loc[(df['latitude']>= 49.180286)&(df['latitude'] <=49.975897 )& (df['longitude']>=73.007664 )&(df['longitude']<=73.216594 )] aktobe = df.loc[(df['latitude']>=43.157950342428 )&(df['latitude'] <= 43.202757)& (df['longitude']>= 57.037496)&(df['longitude']<= 57.309703)] aktay = df.loc[(df['latitude']>= 41.091843)&(df['latitude'] <=42.321688)& (df['longitude']>= 51.0684404142448)&(df['longitude']<= 51.242566)] atyray = df.loc[(df['latitude']>=42.373844 )&(df['latitude'] <=42.878625)& (df['longitude']>= 51.829899)&(df['longitude']<= 51.976558)] taraz = df.loc[(df['latitude']>=43.638035)&(df['latitude'] <= 43.860407)& (df['longitude']>=71.289942 )&(df['longitude']<=71.383097 )] oral = df.loc[(df['latitude']>=53.218562)&(df['latitude'] <=53.91340984)& (df['longitude']>= 51.268246)&(df['longitude']<= 51.5)] kostanay = df.loc[(df['latitude']>=43.226135)&(df['latitude'] <=43.231757)& (df['longitude']>= 63.539098)&(df['longitude']<= 63.682181)] ust_kam = df.loc[(df['latitude']>= 53.218562)&(df['latitude'] <= 53.91340984)& (df['longitude']>=82.548347 )&(df['longitude']<=82.775019 )] turkestan = df.loc[(df['latitude']>=43.253377)&(df['latitude'] <=43.26444)& (df['longitude']>=68.193404 )&(df['longitude']<=68.340979 )] kzyl_orda = df.loc[(df['latitude']>=43.235554 )&(df['latitude'] <=43.241596)& (df['longitude']>= 65.357)&(df['longitude']<=65.5872052968506 )] semei = df.loc[(df['latitude']>=52.305741)&(df['latitude'] <= 52.910023 )& (df['longitude']>= 80.421254)&(df['longitude']<=81.068463)] Almaty is working, but others don't. fig = ff.create_hexbin_mapbox( data_frame=almaty, lat=almaty.latitude, lon=almaty.longitude, nx_hexagon=60, opacity=0.5, labels={"color": "Point Count"}, min_count=5, color_continuous_scale="Viridis", show_original_data=True,zoom=10, original_data_marker=dict(size=4, opacity=0.6, color="deeppink", ) ) fig.update_layout(mapbox_style="open-street-map") fig.show() Working fig = ff.create_hexbin_mapbox( data_frame=astana, lat=astana.latitude, lon=astana.longitude, nx_hexagon=10, opacity=0.5, labels={"color": "Point Count"}, min_count=5, color_continuous_scale="Viridis", show_original_data=True,zoom=10, original_data_marker=dict(size=4, opacity=0.6, color="deeppink", ) ) fig.update_layout(mapbox_style="open-street-map") fig.show() Not working
plt.tricontourf(x,y,z) creating color values outside of data bounds
I am attempting to make compressor and turbine maps colored by efficiency. I have achieved this, but the tricontourf I am attempting leads to level colors outside of where my data even exists. I need to make sure the contour ends at the bounds of my data. Is there a way to achieve this? My code: import numpy as np import matplotlib.pyplot as plt alphaMap = np.array([0.000, 90.000]) NcMap = np.array([0.300, 0.400, 0.500, 0.600, 0.700, 0.750, 0.800, 0.850, 0.900, 0.950, 1.000, 1.050, 1.100, 1.150]) RlineMap = np.array([1.000, 1.200, 1.400, 1.600, 1.800, 2.000, 2.200, 2.400, 2.600, 2.800, 3.000]) WCmap = np.array([[[17.907, 19.339, 20.749, 22.136, 23.498, 24.833, 26.141, 27.420, 28.669, 29.887, 31.011], [24.951, 26.742, 28.485, 30.177, 31.815, 33.397, 34.921, 36.385, 37.788, 39.128, 40.405], [32.682, 34.715, 36.662, 38.520, 40.286, 41.958, 43.533, 45.011, 46.390, 47.669, 48.848], [40.927, 43.115, 45.168, 47.083, 48.858, 50.492, 51.983, 53.331, 54.539, 55.607, 56.537], [49.850, 52.122, 54.195, 56.068, 57.741, 59.215, 60.494, 61.580, 62.479, 63.197, 63.739], [54.798, 57.066, 59.099, 60.897, 62.463, 63.800, 64.913, 65.810, 66.497, 66.983, 67.278], [60.051, 62.252, 64.185, 65.851, 67.255, 68.405, 69.307, 69.973, 70.413, 70.638, 70.675], [65.313, 67.427, 69.262, 70.824, 72.118, 73.153, 73.938, 74.484, 74.803, 74.907, 74.907], [70.995, 72.902, 74.542, 75.920, 77.043, 77.920, 78.560, 78.974, 79.174, 79.198, 79.198], [77.441, 78.904, 80.155, 81.199, 82.042, 82.690, 83.151, 83.434, 83.545, 83.548, 83.548], [84.344, 85.211, 85.952, 86.572, 87.074, 87.460, 87.735, 87.903, 87.967, 87.968, 87.968], [89.305, 89.687, 90.025, 90.320, 90.572, 90.783, 90.953, 91.083, 91.174, 91.227, 91.243], [93.626, 93.712, 93.793, 93.868, 93.939, 94.004, 94.064, 94.120, 94.170, 94.216, 94.257], [95.978, 95.989, 96.000, 96.012, 96.022, 96.033, 96.044, 96.054, 96.064, 96.074, 96.084]], [[17.907, 19.339, 20.749, 22.136, 23.498, 24.833, 26.141, 27.420, 28.669, 29.887, 31.011], [24.951, 26.742, 28.485, 30.177, 31.815, 33.397, 34.921, 36.385, 37.788, 39.128, 40.405], [32.682, 34.715, 36.662, 38.520, 40.286, 41.958, 43.533, 45.011, 46.390, 47.669, 48.848], [40.927, 43.115, 45.168, 47.083, 48.858, 50.492, 51.983, 53.331, 54.539, 55.607, 56.537], [49.850, 52.122, 54.195, 56.068, 57.741, 59.215, 60.494, 61.580, 62.479, 63.197, 63.739], [54.798, 57.066, 59.099, 60.897, 62.463, 63.800, 64.913, 65.810, 66.497, 66.983, 67.278], [60.051, 62.252, 64.185, 65.851, 67.255, 68.405, 69.307, 69.973, 70.413, 70.638, 70.675], [65.313, 67.427, 69.262, 70.824, 72.118, 73.153, 73.938, 74.484, 74.803, 74.907, 74.907], [70.995, 72.902, 74.542, 75.920, 77.043, 77.920, 78.560, 78.974, 79.174, 79.198, 79.198], [77.441, 78.904, 80.155, 81.199, 82.042, 82.690, 83.151, 83.434, 83.545, 83.548, 83.548], [84.344, 85.211, 85.952, 86.572, 87.074, 87.460, 87.735, 87.903, 87.967, 87.968, 87.968], [89.305, 89.687, 90.025, 90.320, 90.572, 90.783, 90.953, 91.083, 91.174, 91.227, 91.243], [93.626, 93.712, 93.793, 93.868, 93.939, 94.004, 94.064, 94.120, 94.170, 94.216, 94.257], [96.084, 96.074, 96.064, 96.054, 96.044, 96.033, 96.022, 96.012, 96.000, 95.989, 95.978]]]) effMap = np.array([[[.8070, .8291, .8461, .8566, .8586, .8497, .8170, .7410, .6022, .3674, .0000], [.8230, .8454, .8628, .8741, .8775, .8708, .8419, .7732, .6477, .4372, .0916], [.8411, .8631, .8805, .8921, .8966, .8918, .8671, .8065, .6959, .5124, .2168], [.8565, .8783, .8957, .9077, .9131, .9099, .8883, .8338, .7340, .5696, .3083], [.8662, .8879, .9055, .9179, .9239, .9219, .9024, .8520, .7600, .6096, .3739], [.8699, .8917, .9093, .9218, .9281, .9265, .9080, .8598, .7721, .6297, .4089], [.8743, .8957, .9130, .9253, .9316, .9304, .9131, .8678, .7858, .6538, .4519], [.8836, .9026, .9179, .9287, .9342, .9331, .9183, .8804, .8128, .7065, .5485], [.8943, .9103, .9230, .9319, .9362, .9351, .9231, .8930, .8406, .7602, .6442], [.9060, .9169, .9253, .9310, .9334, .9321, .9236, .9036, .8703, .8211, .7529], [.9170, .9224, .9264, .9288, .9293, .9280, .9231, .9127, .8962, .8730, .8423], [.9159, .9171, .9176, .9177, .9171, .9159, .9136, .9097, .9042, .8968, .8876], [.9061, .9059, .9055, .9052, .9047, .9042, .9036, .9028, .9018, .9007, .8994], [.8962, .8964, .8965, .8966, .8967, .8968, .8969, .8970, .8971, .8972, .8973]], [[.8070, .8291, .8461, .8566, .8586, .8497, .8170, .7410, .6022, .3674, .0714], [.8230, .8454, .8628, .8741, .8775, .8708, .8419, .7732, .6477, .4372, .0916], [.8411, .8631, .8805, .8921, .8966, .8918, .8671, .8065, .6959, .5124, .2168], [.8565, .8783, .8957, .9077, .9131, .9099, .8883, .8338, .7340, .5696, .3083], [.8662, .8879, .9055, .9179, .9239, .9219, .9024, .8520, .7600, .6096, .3739], [.8699, .8917, .9093, .9218, .9281, .9265, .9080, .8598, .7721, .6297, .4089], [.8743, .8957, .9130, .9253, .9316, .9304, .9131, .8678, .7858, .6538, .4519], [.8836, .9026, .9179, .9287, .9342, .9331, .9183, .8804, .8128, .7065, .5485], [.8943, .9103, .9230, .9319, .9362, .9351, .9231, .8930, .8406, .7602, .6442], [.9060, .9169, .9253, .9310, .9334, .9321, .9236, .9036, .8703, .8211, .7529], [.9170, .9224, .9264, .9288, .9293, .9280, .9231, .9127, .8962, .8730, .8423], [.9159, .9171, .9176, .9177, .9171, .9159, .9136, .9097, .9042, .8968, .8876], [.9061, .9059, .9055, .9052, .9047, .9042, .9036, .9028, .9018, .9007, .8994], [.8962, .8964, .8965, .8966, .8967, .8968, .8969, .8970, .8971, .8972, .8973]]]) PRmap = np.array([[[1.0678, 1.0649, 1.0613, 1.0571, 1.0522, 1.0468, 1.0402, 1.0322, 1.0227, 1.0117, 1.0000], [1.1239, 1.1186, 1.1122, 1.1047, 1.0962, 1.0865, 1.0751, 1.0611, 1.0445, 1.0257, 1.0045], [1.1994, 1.1910, 1.1809, 1.1691, 1.1558, 1.1409, 1.1233, 1.1020, 1.0771, 1.0488, 1.0173], [1.2981, 1.2855, 1.2706, 1.2533, 1.2339, 1.2122, 1.1869, 1.1563, 1.1210, 1.0811, 1.0370], [1.4289, 1.4111, 1.3899, 1.3655, 1.3380, 1.3076, 1.2720, 1.2295, 1.1804, 1.1254, 1.0654], [1.5118, 1.4909, 1.4661, 1.4375, 1.4052, 1.3695, 1.3278, 1.2779, 1.2205, 1.1565, 1.0868], [1.6070, 1.5827, 1.5538, 1.5205, 1.4831, 1.4417, 1.3934, 1.3358, 1.2697, 1.1962, 1.1165], [1.7160, 1.6881, 1.6555, 1.6183, 1.5767, 1.5312, 1.4785, 1.4160, 1.3448, 1.2660, 1.1808], [1.8402, 1.8086, 1.7724, 1.7318, 1.6869, 1.6381, 1.5824, 1.5170, 1.4430, 1.3615, 1.2736], [1.9930, 1.9587, 1.9206, 1.8788, 1.8336, 1.7852, 1.7309, 1.6685, 1.5988, 1.5225, 1.4405], [2.1593, 2.1257, 2.0899, 2.0518, 2.0117, 1.9695, 1.9235, 1.8724, 1.8163, 1.7557, 1.6909], [2.2764, 2.2510, 2.2248, 2.1978, 2.1701, 2.1416, 2.1118, 2.0801, 2.0464, 2.0108, 1.9735], [2.3771, 2.3664, 2.3557, 2.3448, 2.3339, 2.3229, 2.3118, 2.3004, 2.2887, 2.2768, 2.2646], [2.4559, 2.4538, 2.4516, 2.4495, 2.4473, 2.4452, 2.443, 2.4409, 2.4387, 2.4365, 2.4343]], [[1.0678, 1.0649, 1.0613, 1.0571, 1.0522, 1.0468, 1.0402, 1.0322, 1.0227, 1.0117, 1.0000], [1.1239, 1.1186, 1.1122, 1.1047, 1.0962, 1.0865, 1.0751, 1.0611, 1.0445, 1.0257, 1.0045], [1.1994, 1.1910, 1.1809, 1.1691, 1.1558, 1.1409, 1.1233, 1.1020, 1.0771, 1.0488, 1.0173], [1.2981, 1.2855, 1.2706, 1.2533, 1.2339, 1.2122, 1.1869, 1.1563, 1.1210, 1.0811, 1.0370], [1.4289, 1.4111, 1.3899, 1.3655, 1.3380, 1.3076, 1.2720, 1.2295, 1.1804, 1.1254, 1.0654], [1.5118, 1.4909, 1.4661, 1.4375, 1.4052, 1.3695, 1.3278, 1.2779, 1.2205, 1.1565, 1.0868], [1.6070, 1.5827, 1.5538, 1.5205, 1.4831, 1.4417, 1.3934, 1.3358, 1.2697, 1.1962, 1.1165], [1.7160, 1.6881, 1.6555, 1.6183, 1.5767, 1.5312, 1.4785, 1.4160, 1.3448, 1.2660, 1.1808], [1.8402, 1.8086, 1.7724, 1.7318, 1.6869, 1.6381, 1.5824, 1.5170, 1.4430, 1.3615, 1.2736], [1.9930, 1.9587, 1.9206, 1.8788, 1.8336, 1.7852, 1.7309, 1.6685, 1.5988, 1.5225, 1.4405], [2.1593, 2.1257, 2.0899, 2.0518, 2.0117, 1.9695, 1.9235, 1.8724, 1.8163, 1.7557, 1.6909], [2.2764, 2.2510, 2.2248, 2.1978, 2.1701, 2.1416, 2.1118, 2.0801, 2.0464, 2.0108, 1.9735], [2.3771, 2.3664, 2.3557, 2.3448, 2.3339, 2.3229, 2.3118, 2.3004, 2.2887, 2.2768, 2.2646], [2.4343, 2.4365, 2.4387, 2.4409, 2.4430, 2.4452, 2.4473, 2.4495, 2.4516, 2.4538, 2.4559]]]) label = [] for x in NcMap: label.append(x*100) for i in range(0,14): plt.annotate('{0}%'.format(round(label[i],2)),xy = ((flowmax[i],PRmax[i])), textcoords='offset points', xytext=(0,6), ha = 'center', color = 'b') plt.xlim(0,1) plt.ylim(1,8) plt.ylabel(r'$PR_{off}$', fontsize=16) plt.xlabel(r'$\.m_{c,off} [kg/s]$', fontsize=16) x = WCmap[0,:14,:] x = x.flatten().tolist() y = PRmap[0,:14,:] y = y.flatten().tolist() z = effMap[0,:14,:] z = z.flatten().tolist() plt.tricontourf(x,y,z, cmap = 'jet') cbar = plt.colorbar() cbar.set_label(r'$\eta_{off}$', fontsize=16) plt.show() Compressor Map Plot
How to realize 1 month `step` in Bokeh DateRangeSlider?
The Bokeh DateRangeSlider widget requires int values for its step attribute which must be the time value in milliseconds. It works well when the step is set to seconds, minutes, hours, days or years. However I need a month resolution on the slider. When the step is set to 31 days it works well for the start date until March when instead of 1 March I get 4 March. Then the shift from 1th of the month in the displayed value gets bigger and bigger. I want to be able to set and get displayed the slider range on both sides always to be the 1th day of the month e.g. 1 March, 1 April, 1 May, 1 June etc... like it is in the DataFrame. Considering the following code, what would be the best way to realize it (possibly using a JS callback) ? import pandas as pd from bokeh.plotting import show from bokeh.models import DateRangeSlider data = {'date_start': ['201812', '201901', '201902', '201903', '201904', '201905', '201906', '201907', '201908', '201909', '201910', '201911'], 'date_end': [ '201901', '201902', '201903', '201904', '201905', '201906', '201907', '201908', '201909', '201910', '201911', '201912'], 'values' : [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]} df = pd.DataFrame(data) df['Start'] = pd.to_datetime(df['date_start'], format='%Y%m') df['End'] = pd.to_datetime(df['date_end'], format='%Y%m') start_date = df['Start'].min() end_date = df['End'].max() range_slider = DateRangeSlider(start=start_date, end=end_date, value=(start_date, end_date), step=31*24*60*60*1000, title="Date Range", callback_policy = 'mouseup', tooltips = False, width=600) show(range_slider)import pandas as pd from bokeh.plotting import show from bokeh.models import DateRangeSlider data = {'date_start': ['201812', '201901', '201902', '201903', '201904', '201905', '201906', '201907', '201908', '201909', '201910', '201911'], 'date_end': [ '201901', '201902', '201903', '201904', '201905', '201906', '201907', '201908', '201909', '201910', '201911', '201912'], 'values' : [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]} df = pd.DataFrame(data) df['Start'] = pd.to_datetime(df['date_start'], format='%Y%m') df['End'] = pd.to_datetime(df['date_end'], format='%Y%m') start_date = df['Start'].min() end_date = df['End'].max() range_slider = DateRangeSlider(start=start_date, end=end_date, value=(start_date, end_date), step=31*24*60*60*1000, title="Date Range", callback_policy = 'mouseup', tooltips = False, width=600) show(range_slider)
After some struggling I came up with this JS callback which temporary changes the step to 1 day in order to be able to correct the date. It also changes temporary the range so that when the step is restored the slider handle remains on its position. Far from perfect but working: import pandas as pd from bokeh.plotting import show from bokeh.models import CustomJS, DateRangeSlider data = {'date_start': ['201812', '201901', '201902', '201903', '201904', '201905', '201906', '201907', '201908', '201909', '201910', '201911'], 'date_end': [ '201901', '201902', '201903', '201904', '201905', '201906', '201907', '201908', '201909', '201910', '201911', '201912'], 'values' : [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]} df = pd.DataFrame(data) df['Start'] = pd.to_datetime(df['date_start'], format='%Y%m') df['End'] = pd.to_datetime(df['date_end'], format='%Y%m') start_date = df['Start'].min() end_date = df['End'].max() range_slider = DateRangeSlider(start=start_date, end=end_date, value=(start_date, end_date), step=31*24*60*60*1000, title="Date Range", callback_policy = 'mouseup', tooltips = False, width=600) code = ''' console.log('start, end', cb_obj.start, cb_obj.end) for (i in cb_obj.value) { if (getDay(cb_obj.value[i]) != 1) { correctDate(day, i) } } function getDay(value) { date = new Date(value) str_date = date.toString() day = str_date.split(' ')[2] return Number(day) } function correctDate(day, side) { if (day < 15) { console.log('day < 15') difference = day - 1 difference_milliseconds = -1 * difference*24*60*60*1000 } else { console.log('day >= 15') difference = 0 new_day = -1 while(new_day != 1) { difference_milliseconds = difference*24*60*60*1000 new_date = new Date(cb_obj.value[0] + difference_milliseconds) new_day = Number(new_date.getDate()) difference += 1 } } cb_obj.step = 1*24*60*60*1000 // set slider step to 1 day to be able to correct if (side == 0) { cb_obj.start = cb_obj.start + difference_milliseconds cb_obj.value = [cb_obj.value[0] + difference_milliseconds, cb_obj.value[1]] } else if (side == 1) { cb_obj.end = cb_obj.end + difference_milliseconds + 4*24*60*60*1000 cb_obj.value = [cb_obj.value[0], cb_obj.value[1] + difference_milliseconds] } setTimeout(resetStep, 50, cb_obj) // reset step to 31 days } function resetStep(cb_obj) { cb_obj.step = 31*24*60*60*1000 } ''' range_slider.js_on_change('value_throttled', CustomJS(args = {'end_date': end_date}, code=code)) show(range_slider) Or maybe the best option is not to use the DateRangeSlider at all fo the month step. The solution below uses a RangeSlider in combination with a Div to realize the same functionality which looks much nicer: import pandas as pd from bokeh.plotting import show from bokeh.models import RangeSlider, Div, Column, CustomJS data = {'date_start': ['2018-12', '2019-01', '2019-02', '2019-03', '2019-04', '2019-05', '2019-06', '2019-07', '2019-08', '2019-09', '2019-10', '2019-11'], 'date_end': [ '2019-01', '2019-02', '2019-03', '2019-04', '2019-05', '2019-06', '2019-07', '2019-08', '2019-09', '2019-10', '2019-11', '2019-12'], 'values' : [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]} df = pd.DataFrame(data) df['Start'] = pd.to_datetime(df['date_start'], format='%Y-%m') df['End'] = pd.to_datetime(df['date_end'], format='%Y-%m') number_dates = len(list(df.date_start.unique())) start_dates = df.date_start.to_list() end_dates = df.date_end.to_list() range_slider = RangeSlider(start=0, end=number_dates, value=(0, number_dates), step=1, title="", callback_policy = 'mouseup', tooltips = False, width=600, show_value = False) div = Div(text = "Date Range: <b>" + str(start_dates[range_slider.value[0]]) + ' . . . ' + str(end_dates[range_slider.value[1]-1]) + '</b>', render_as_text = False, width = 575) code = ''' range = Math.round(Number(cb_obj.value[1] - cb_obj.value[0]), 10) range = range < 10 ? '0' + range : range div.text = "Date Range: <b>" + start_dates[Math.round(cb_obj.value[0], 10)] + ' . . . ' + end_dates[Math.round(cb_obj.value[1], 10) + -1] + '</b>' ''' range_slider.js_on_change('value_throttled', CustomJS(args = {'div': div, 'start_dates': start_dates, 'end_dates': end_dates}, code=code)) show(Column(div, range_slider))
hbar bokeh 1.3.4 with categorical data
I am trying to build a categorical plot with hbar in bokeh, though it seems a bit odd that it does not follow the same concept as the vbar. I have tried few variations and I still have not been able to plot the data, I am only getting an empty canvas. If someone could help me out, it would be much appreciated. I am using bokeh 1.3.4 in my system and in an webapp I am building in Flask, so it has to be either this version or below(feels a bit demanding, but it is software requirements). I have done it with pandas_bokeh which makes it very simple, though I am adding interactivity to the plots to allow the viewer to play around and pandas_bokeh does the job and you ended up not learning it properly. webapp draft so far rX = df3.index.values xL = ['Dublin New', 'Ireland New','Dublin Existing','Ireland Existing'] labelDict = {'2010': xL, '2011': xL, '2012': xL, '2013': xL, '2014': xL,'2015': xL,'2016': xL,'2017': xL, '2018': xL} sourceT = ColumnDataSource(data=dict(x=df3.index.values, y=df3['Dublin New'], y1=df3['Ireland New'], y2=df3['Dublin Existing'], y3=df3['Ireland Existing'])) pT = figure(y_range=FactorRange(*labelDict), plot_height=350, plot_width=550, title='Properties Transactions in Ireland', tools='pan, wheel_zoom, box_zoom, reset') pT.hbar(y=dodge('x', -0.5, range=pT.y_range), height=0.3, right='y', fill_color="#FDE724", source=sourceT) #pT.hbar(y=dodge('x', -0.25, range=pT.y_range), height=0.3, right='y1', fill_color='#35B778', source=sourceT) show(pT) Here is the plot I would like to reproduce using bokeh, instead pandas_bokeh. Thanks in advance for the help.
The value for the range parameter of the dodge should be the actual range: range=pT.y_range # GOOD You are passing the range end property, which is a number: range=pT.y_range.end # BAD EDIT: Without a complete, minimal reproducer, it is not possible to directly fix your code. The best that can be offered is a complete working example that demonstrates that hbar does work exactly equivalently to vbar, that hopefully will be useful to you by comparison, to figure out where your full code strays: from bokeh.io import show from bokeh.models import ColumnDataSource from bokeh.plotting import figure from bokeh.transform import dodge fruits = ['Apples', 'Pears', 'Nectarines', 'Plums', 'Grapes', 'Strawberries'] years = ['2015', '2016', '2017'] data = {'fruits' : fruits, '2015' : [2, 1, 4, 3, 2, 4], '2016' : [5, 3, 3, 2, 4, 6], '2017' : [3, 2, 4, 4, 5, 3]} source = ColumnDataSource(data=data) p = figure(y_range=fruits, x_range=(0, 10), plot_width=250, title="Fruit Counts by Year", toolbar_location=None, tools="") p.hbar(y=dodge('fruits', -0.25, range=p.y_range), right='2015', height=0.2, source=source, color="#c9d9d3") p.hbar(y=dodge('fruits', 0.0, range=p.y_range), right='2016', height=0.2, source=source, color="#718dbf") p.hbar(y=dodge('fruits', 0.25, range=p.y_range), right='2017', height=0.2, source=source, color="#e84d60") p.y_range.range_padding = 0.1 p.ygrid.grid_line_color = None show(p)
#bigreddot Thanks a lot. I followed your approach and it works smoothly. I will try to work reserve the axis as I would rather to have the years in the yaxis. Anyhow I really appreciated your help. varT = ['Dublin New', 'Ireland New', 'Dublin Existing','Ireland Existing'] yearsT = df3.index.values.tolist() dataT = {'var': var, '2010': df3.iloc[0].values, '2011': df3.iloc[1].values, '2012': df3.iloc[2].values, '2013': df3.iloc[3].values, '2014': df3.iloc[4].values, '2015': df3.iloc[5].values, '2016': df3.iloc[6].values, '2017': df3.iloc[7].values, '2018': df3.iloc[8].values, } sourceTs = ColumnDataSource(data=dataT) pT1 = figure(y_range=var, x_range=(0, df3.values.max()), plot_width=450, title='Properties Transactions in Ireland', tools='pan, wheel_zoom, box_zoom, reset') pT1.hbar(y=dodge('var', -0.4, range=pT1.y_range), right='2010', height=0.1, source=sourceTs, color='#440154', legend=value('2010')) pT1.hbar(y=dodge('var', -0.3, range=pT1.y_range), right='2011', height=0.1, source=sourceTs, color='#46317E', legend=value('2011')) pT1.hbar(y=dodge('var', -0.2, range=pT1.y_range), right='2012', height=0.1, source=sourceTs, color='#365A8C', legend=value('2012')) pT1.hbar(y=dodge('var', -0.1, range=pT1.y_range), right='2013', height=0.1, source=sourceTs, color='#277E8E', legend=value('2013')) pT1.hbar(y=dodge('var', 0, range=pT1.y_range), right='2014', height=0.1, source=sourceTs, color='#1EA087', legend=value('2014')) pT1.hbar(y=dodge('var', 0.1, range=pT1.y_range), right='2015', height=0.1, source=sourceTs, color='#49C16D', legend=value('2015')) pT1.hbar(y=dodge('var', 0.2, range=pT1.y_range), right='2016', height=0.1, source=sourceTs, color='#9DD93A', legend=value('2016')) pT1.hbar(y=dodge('var', 0.3, range=pT1.y_range), right='2017', height=0.1, source=sourceTs, color='#FDE724', legend=value('2017')) pT1.hbar(y=dodge('var', 0.4, range=pT1.y_range), right='2018', height=0.1, source=sourceTs, color='#AADB32', legend=value('2018')) pT1.legend.location='bottom_right' #pT1.y_range.range_padding = 0.1 pT1.grid.grid_line_color = None tick_labels_pt = {'10000':'10K','20000':'20K','30000':'30K','40000':'40K','50000':'50K'} pT1.xaxis.major_label_overrides = tick_labels_pt pT1.legend.background_fill_alpha=None pT1.legend.border_line_alpha=0 pT1.legend.label_text_font_size = "11px" pT1.legend.click_policy="hide" pT1.title.text_font_size = '15px' pT1.axis.major_label_text_font_style = 'bold' #pT1.xaxis.major_label_text_font_style = 'bold' pT1.toolbar.autohide = True show(pT1) Here is the outcome: with the axis reversed: varpti = ['Dublin New', 'Ireland New', 'Dublin Existing','Ireland Existing'] #the values of the y axis has to be in str format yearspti = '2010','2011','2012', '2013', '2014', '2015', '2016', '2017', '2018' #df3.index.values.tolist() datapti = {'years': yearspti, 'Dublin New': df3['Dublin New'].values, 'Ireland New': df3['Ireland New'].values, 'Dublin Existing': df3['Dublin Existing'].values, 'Ireland Existing': df3['Ireland Existing'].values } sourcepti = ColumnDataSource(data=datapti) pti = figure(y_range=yearspti, x_range=(0, df3.values.max()), plot_height=500, plot_width=450, title='Properties Transactions in Ireland', tools='pan, wheel_zoom, box_zoom, reset') pti.hbar(y=dodge('years', -0.2, range=pti.y_range), right='Dublin New', height=0.1, source=sourcepti, color='#440154', legend=value('Dublin New')) pti.hbar(y=dodge('years', 0, range=pti.y_range), right='Ireland New', height=0.1, source=sourcepti, color='#30678D', legend=value('Ireland New')) pti.hbar(y=dodge('years', 0.2, range=pti.y_range), right='Dublin Existing', height=0.1, source=sourcepti, color='#35B778', legend=value('Dublin Exsiting')) pti.hbar(y=dodge('years', 0.4, range=pti.y_range), right='Ireland Existing', height=0.1, source=sourcepti, color='#FDE724', legend=value('Ireland Exsiting'))