Bokeh Columnsourcedata нахождение мин и макс - PullRequest
0 голосов
/ 21 сентября 2018

Я пытаюсь найти максимальное и минимальное значение для каждой категории в source = columndatasource, где мои данные об акциях организованы в столбцы по (Open, High, Low, Close, AdjClose, Volume и т. Д ....)

Я пытался использовать,

 max(source.data['Close'])
 min(source.data['Close']) 

, однако проблема с max (source.data ['Open']) заключается в том, что значения не обновляются, когда я обновляю свои данные при использовании ползунка и выбираюwidgets.

Есть ли способ, которым я могу найти минимальное и максимальное значения каждого столбца, которые будут обновляться каждый раз, когда я обновляю свои данные?

from math import pi
import pandas as pd
import numpy as np
import datetime
import time
from datetime import date
from bokeh.layouts import row, widgetbox, column
from bokeh.models import DataRange1d, LinearAxis, Range1d, ColumnDataSource, PrintfTickFormatter, CDSView, BooleanFilter, NumeralTickFormatter
from bokeh.models.widgets import PreText, Select, DateRangeSlider, Button, DataTable, TableColumn, NumberFormatter
from bokeh.io import curdoc, show, reset_output
from bokeh.plotting import figure, output_file

DEFAULT_TICKERS = ['AAPL','GOOG','NFLX', 'TSLA']
ticker1 = Select(value='AAPL', options = DEFAULT_TICKERS)
range_slider1 = DateRangeSlider(start=date(2014,1,1) , end=date(2017,1,1), value=(date(2014,2,1),date(2016,3,1)), step=1)


def load_ticker(ticker):
    fname = ( '%s.csv' % ticker.lower())
    data = pd.read_csv( fname, header = None, parse_dates = ['Date'],
                  names =['Date','Open','High','Low','Close','AdjClose','Volume'])
    return data

def get_data(t1):
    data = load_ticker(t1)
    return data

def ticker1_change(attrname, old, new):
    update()

def range_slider_change(attrname, old, new):
    update()

def update(selected=None):
    t1 = ticker1.value

    if isinstance(range_slider1.value[0], (int, float)):
        # pandas expects nanoseconds since epoch
        start_date = pd.Timestamp(float(range_slider1.value[0])*1e6)
        end_date = pd.Timestamp(float(range_slider1.value[1])*1e6)
    else:
        start_date = pd.Timestamp(range_slider1.value[0])
        end_date = pd.Timestamp(range_slider1.value[1])

    datarange = get_data(t1)
    datarange['Date'] = pd.to_datetime(datarange['Date'])
    mask = (datarange['Date'] > start_date) & (datarange['Date'] <= end_date)
    data = datarange.loc[mask]
    source.data = source.from_df(data)
    p.title.text = t1

data = get_data(ticker1.value)
source = ColumnDataSource(data)

p = figure(plot_width=900, plot_height=400, x_axis_type='datetime', y_range = Range1d(min(source.data['Close']), max(source.data['Close'])))
p.grid.grid_line_alpha = 0.3
p.line('Date', 'Close', source=source)

ticker1.on_change('value', ticker1_change)
range_slider1.on_change('value', range_slider_change)
update()

layout = column(ticker1,range_slider1, p)                                                              
curdoc().add_root(layout)
curdoc().title = "Stock"

1 Ответ

0 голосов
/ 23 февраля 2019
  • Да.Ваш вопрос немного запутан

Краткий ответ: Вам нужно создать еще один «источник», содержащий значения max и min.

Длинный ответ: Ваш код работает неправильно.Я скопировал / вставил ваш код ^^ и запустил его на локальном сервере боке.Нет вывода, т.е. вам нужно сначала исправить код.

Но, допустим, ваш код запущен.На данный момент единственный способ автоматически обновлять макс или мин каждый раз, когда вы меняете bokeh slider или другое значение виджета, - это создать другой источник, скажем, source2.

source = ColumnDataSource(data_max_min)

Тогда, сопоставьте ключи с тем же значением.В вашем примере ^^ это, скорее всего, будет дата в словаре (data_max_min).

Например,

pd = read_csv('.../AAPL.csv', header=0, index=None)
aapl_close = pd.DataFrame(aapl_df['close'])
aapl_close.index = aapl_df.date
aapl_close

    close
date    
2018/11/23  172.29
2018/11/26  174.62
2018/11/27  174.24

Я предполагаю, что вы хотите получить максимальное и минимальное значение длякаждый временной диапазон, который вы хотите анализировать по мере поступления (или что-то в этом роде).Мой код просто получит максимум для каждого закрытия (* это будет то же значение), как в качестве примера.Если вы этого не понимаете, я бы порекомендовал прочесть часть документации еще раз.

aapl_max_df = pd.DataFrame()
aapl_max_df['max'] = [max(prices) for prices in aapl_close['close']]
aapl_max_df.index = aapl_close.index

aapl_max_min = {}
dates = aapl_max_min.index
for i in range(aapl_max_min.shape[0]):
    aapl_max_min[aapl_max_min.index.values[i]] = aapl_max_min['max'].values[i]

source2 = ColumnDataSource(data=aapl_max_min[dates[0]])

Затем, когда вы обновите ползунок, вам нужно будет обновить «дату» для обоих источников.Это что-то еще не в вашем коде.В Интернете есть несколько примеров того, как это сделать (https://github.com/bokeh/bokeh/tree/master/examples/app/gapminder).

вот так ->

def slider_update(attrname, old, new):
    year = slider.value
    label.text = str(year)
    source.data = data[year]
    source2.data = data[year]
...