可编辑绘图表中的初始化和重新计算

问题描述 投票:0回答:1

我目前正在研究一个项目,以实现交互式库存评估。这要求用户通过输入股票行情自动收录器来选择股票,然后该用户应能够调整股票驱动程序并观察这些变化对公司估值的影响。

为了实现这一目标,必须首先在表格中填充库存信息,然后根据用户编辑的变量更新计算。理想情况下,可以按照示例“更新同一表的列” here来更新表本身内的计算。但是,就我而言,我正在努力将表的初始化与库存选择的输出结合在一起,并在用户修改表内容时更新表的计算。

我在下面整理了一个非常简单,简短的示例。在这种情况下,我认为将库存数据和计算输出分离到两个单独的表中可能会更简单。这也是我想要做的事情,并且比在一个表中包含所有内容都代表了更广泛的用例。

我已经对代码进行了一些注释,以便使我的逻辑很清楚。但是代码的基本概述如下:

((i)请求报价员的用户输入(在此示例中为stock1或stock2)。

((ii)显示代码,如果代码不正确,则显示错误消息。

((iii)将库存数据存储在中间数据框中(根据示例1 here。]]

((iv)用当前选定股票的选定股票数据填充FCFf表。

((v)使用来自FCFf数据的数据计算现值

[v)中似乎出现了我的问题:我的方法涉及将(iii)中的库存数据加载到stock_df中,将(iv)中的fcff数据加载到fcff_df中,并覆盖stock_df中的fcff字段与fcff_df中的那些。不幸的是,在手动更改任何FCFf值(例如,fcff_fy3列中的值)时,评估表不会更新:相反,我得到了一个错误

TypeError: ufunc 'true_divide' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''

令我震惊的是,也许用户输入的解释类型与单元格的类型不同,而是被视为字符串?

但是,无论如何,艾米的方法似乎有点不合常规,我想知道是否有更好的解决方案?

注意,我还希望能够计算对单个表进行更改的时间。例如,我是否将估值表和FCFf表合并为一个,并且还添加了do_pv中使用的折现率'r'作为可编辑字段,我该怎么做?谢谢您的帮助。

示例数据和代码:

import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output, State
import dash_table
import pandas as pd

from dash_table.Format import Format, Scheme, Sign, Symbol

df = pd.DataFrame(data = { 'ticker' :  ['stock1', 'stock2'], 'r' : [0.1, 0.2], 'fcff_fy1' : [7902, 9409] , 'fcff_fy2' : [13912, 68969], 'fcff_fy3' : [11309, 7154], 'fcff_fy4' : [13912, 68969], 'fcff_fy5' : [76158,   84090]   })
fcff_cols = ['fcff_fy1', 'fcff_fy2', 'fcff_fy3', 'fcff_fy4', 'fcff_fy5']
valuation_cols = ['Item', 'Valuation']

external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
app.config.suppress_callback_exceptions = True
app.css.append_css({
    "external_url": "https://codepen.io/chriddyp/pen/bWLwgP.css"
})

app.layout = html.Div([
    html.H1('Stock Valuation'),
    html.H5('Choose stock from stock1, stock2'),
    dcc.Input(id='stock-id', value='stock1', type='text'),  #human text input of stock ticker
    html.Div(id='my-tick'), # Output to identify and inform user whether ticker selection is vald
    html.Hr(),
    html.Div(id='stock-data', style={'display': 'none'}), #intermediate storage of stock data dataframe.
    html.H5('FCFf drivers'),
    dash_table.DataTable(id='fcff-table', # Free cashflow table for selected stock
                         columns = [{"name": i, "id": i, 'format': Format(precision=2)} for i in (['Item'] + fcff_cols)],
                         data = ['FCFf'] + [0 for x in fcff_cols], editable = True),
    html.Hr(),
    html.H5('PV'),
    html.Div(dash_table.DataTable(id='valn-table', columns=[{"name": i, "id": i} for i in valuation_cols], data=[0 for x in ['Valuation']], editable = True)), # Valuation table, fed from FCff table
])

# Fill FCFf table with selected stock data
@ app.callback(
    [Output('fcff-table', 'columns'),
     Output('fcff-table', 'data')],
    [Input('stock-data', 'children')])
def display_output(df):
    stock_df = pd.read_json(df)
    fcff_table = pd.DataFrame(columns = fcff_cols, data = stock_df[fcff_cols].values.round(2), index=['FCFf'])
    fcff_table.reset_index(inplace=True)
    fcff_table.rename(columns={'index': 'Item'}, inplace=True)
    fcff_col_param = []
    for col in ['Item'] + fcff_cols:
        fcff_col_param.append({"name": str(col), "id": str(col)})
    return [fcff_col_param, fcff_table.to_dict('records')]


# Read data in from editable FaCFf table, and use to calculate and populate valn-table
@app.callback(
    [Output('valn-table', 'columns'),
     Output('valn-table', 'data')],
    [Input('fcff-table', 'data'),
     Input('stock-data', 'children')])
def display_valn(f_data, df):
    stock_df = pd.read_json(df) # Read current stock data from intermediate div in html.
    fcff_df = pd.DataFrame(f_data) # Convert FCFf table data to dataframe
    fcff_df = fcff_df[fcff_df.Item == 'FCFf'].drop('Item', axis=1)
    fcff_df.columns = fcff_cols

    stock_df[fcff_cols] = fcff_df[fcff_cols].values # overwrite fcff data with fcff data from the table, allowing users to change fcff assumptions.
    stock_df = do_pv(stock_df) # do PV of cashflows using stock's discount rate, r

    # construct valuation table output for display in valn-table
    data = [['Present Value of forecast FCFf (m)', stock_df['pv'].values[0].round(2)], ['Discount rate (r)', stock_df['r'].values[0].round(3)]],

table = pd.DataFrame(data, columns = ['Item', 'Valuation'])

    dt_col_param = [{"name": 'Item', "id": 'Item'}, {"name": 'Valuation', "id": 'Valuation'}]
    return [dt_col_param, table.to_dict('records')]

# Select stock for consideration via manual entry of ticker.
@app.callback(
    Output('my-tick', 'children'),
    [Input('stock-id', 'value')]
)
def update_output_ticker(input_value):
    if not input_value in df.ticker.unique():
        return 'Incorrect ticker'
    else:
        return df[df.ticker == input_value].ticker

# Store selected stock data dataframe in intermediate step.
@app.callback(Output('stock-data', 'children'),
              [Input('stock-id', 'value')])
def do_stock_df(selected_ticker):
    stock_df = df[df.ticker == selected_ticker]
    return stock_df.to_json()

def do_pv(df):
    df['pv'] = 0
    # pv of 5-year forecasts
    for i in range(1, 5):
        df.pv += df['fcff_fy' + str(i)].values[0] / ((1 + df.r.values[0]) ** i)
    return df

if __name__ == '__main__':
    app.run_server(debug=True)
python plotly-dash plotly-python
1个回答
1
投票

尝试将do_pv模块更改为以下内容,看起来像是在编辑表格后,将值作为导致此错误的字符串提取。

def do_pv(df):
    df['pv'] = 0
    # pv of 5-year forecasts
    for i in range(1, 5):
        #its string for the edited columns
        print(type(df['fcff_fy' + str(i)].values[0])) 
        df['pv'] +=  float(df['fcff_fy' + str(i)].values[0]) / float((1 + df.r.values[0]) ** i)
    return df
© www.soinside.com 2019 - 2024. All rights reserved.