Bokeh:是否可以像熊猫DataFrame一样,使用ColumnDataSource基于条件创建字形



我正在Bokeh中创建矩形,这些矩形基于条件:

rect1 = p.rect(df.index[df.Close > df.Open],(df["Open"][df.index[df.Close > df.Open]]+df["Close"][df.index[df.Close > df.Open]])/2, hours_12, (df["Close"][df.index[df.Close > df.Open]]-df["Open"][df.index[df.Close > df.Open]]),fill_color="#CCCCCC", line_color="black")

因此,只有当"关闭"列中的值高于"打开"列的值时,它才会创建rect。Everething在不创建ColumnDataSource的情况下运行良好。如果我尝试使用ColumnDataSource,它不会起作用,所以我想:嘿,没关系,我会在这里使用熊猫。

问题出在尝试使用悬停工具时。它不喜欢熊猫DataFrame。所以我不能同时拥有条件和悬停工具。我得选一个。

有解决办法吗?

非常感谢

当然。rect的位置自变量是xywidthheightangledilate

只需创建一个具有所需列的数据源,并传递列的名称来代替您的数据:

index = df.index[df.Close > df.Open]
close =df.loc[index, 'Close']
open =df.loc[index, 'Open']
cds = ColumnDataSource(dict(x=index, y=(open + close) / 2, width=hours_12, height=(close - open)))
rect1 = p.rect('x', 'y', 'width', 'height', source=cds, fill_color="#CCCCCC", line_color="black")

请注意,列可以有任何名称。唯一重要的是在rect的参数中使用相同的名称。

好吧,所以我找到了一个主要归功于此的解决方案:如何正确处理bokeh/holowiews热图图中的日期时间和分类轴?

我的代码有两个问题:当我将pandas数据帧转换为ColumnDataSource时,我需要将date转换为datetime对象。

x_green = [
date.to_datetime64().astype('M8[ms]').astype('O')
for date in df_green.index.to_list()
]

之后,我需要明白,我不能在ColumnDataSource列之间进行与pandas列相同的(数学(运算。所以我需要从pandas列中准备数据(字典(,然后制作ColumnDataSource,然后我最终可以使用HoverTool,这是一直以来的主要内容。然后它终于奏效了。完整代码在这里:

from datetime import datetime
from pandas_datareader import data
import pandas as pd
from bokeh.plotting import figure, show, ColumnDataSource, output_file
from bokeh.io import output_notebook
from bokeh.models import HoverTool
output_notebook()
start=datetime(2020,1,1)
end=datetime(2020,4,3)
name="NSRGY" #nestle
#getting stock data from yahoo
df=(data.DataReader(name=name,data_source="yahoo",start=start,end=end))
#making two datasets based on criteria 
df_green=df[df.Close > df.Open]
df_red=df[df.Close < df.Open]
#converting date to datetime : otherwise ColumnDataSource is not working
x_green = [
date.to_datetime64().astype('M8[ms]').astype('O')
for date in df_green.index.to_list()
]
x_red = [
date.to_datetime64().astype('M8[ms]').astype('O')
for date in df_red.index.to_list()
]

#preparing data for each of CDS
data_green= {
'date':x_green,
'open':df_green.Open.tolist(),
'close':df_green.Close.tolist(),
'y':((df_green.Open + df_green.Close)/2).tolist(),
'height':((df_green.Close - df_green.Open)).tolist(),
'low':df_green.Low.tolist(),
'high':df_green.High.tolist(),
}
data_red= {
'date':x_red,
'open':df_red.Open.tolist(),
'close':df_red.Close.tolist(),
'y':((df_red.Open + df_red.Close)/2).tolist(),
'height':((df_red.Close - df_red.Open)).tolist(),
'low':df_red.Low.tolist(),
'high':df_red.High.tolist(),
}

source_green=ColumnDataSource(data=data_green)
source_red=ColumnDataSource(data=data_red)
p=figure(x_axis_type="datetime", height=300,sizing_mode="scale_width")
p.title.text = "Candlestick Chart"
hours_12=12*60*60*1000
ciara_green = p.segment(x0="date", y0='low', x1="date", y1='high', color='black', source=source_green)
ciara_red = p.segment(x0="date", y0='low', x1="date", y1='high', color='black', source=source_red)
rect_green = p.rect(x='date',y = 'y', width = hours_12,height = ('height'), fill_color="green", source=source_green)
rect_red = p.rect(x='date',y = 'y', width = hours_12,height = ('height'), fill_color="red", source=source_red)
rect_hover = HoverTool(renderers=[rect_green,rect_red],
tooltips=[("Company",name),('Open value','@{open}'),('Close value','@{close}'),('Date','@date{%F}')], formatters={'date':'datetime'})
p.add_tools(rect_hover)
show(p)

我想还有更优雅的方法可以做到这一点,但这就是我所能做到的。请记住,由于HoverTool需要ColumnDataSource,所以大部分代码都已完成。否则,只需熊猫数据帧和我最初的问题中的两行(更长的(代码就可以轻松完成。如果你熟悉情节:在图形中实现悬停功能是同样的痛苦吗?谢谢

最新更新