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

Python 可编辑绘图仪中的初始化和重新计算,python,plotly-dash,plotly-python,Python,Plotly Dash,Plotly Python,我目前正在进行一个项目,以实现交互式股票估值。这要求用户通过输入股票代码来选择股票,然后用户应该能够调整股票驱动因素,并观察这些变化对公司估值的影响 为了实现这一点,必须首先用股票信息填充表格,然后根据用户编辑的变量更新计算。理想情况下,可以在表本身内更新计算,如“更新同一表的列”示例所示。然而,在我的例子中,我很难将表的初始化与股票选择的输出结合起来,并在用户修改表的内容时更新表的计算 我在下面列出了一个非常简单、简略的示例。在本例中,我认为将股票数据和计算输出分离到两个单独的表中可能更简单。

我目前正在进行一个项目,以实现交互式股票估值。这要求用户通过输入股票代码来选择股票,然后用户应该能够调整股票驱动因素,并观察这些变化对公司估值的影响

为了实现这一点,必须首先用股票信息填充表格,然后根据用户编辑的变量更新计算。理想情况下,可以在表本身内更新计算,如“更新同一表的列”示例所示。然而,在我的例子中,我很难将表的初始化与股票选择的输出结合起来,并在用户修改表的内容时更新表的计算

我在下面列出了一个非常简单、简略的示例。在本例中,我认为将股票数据和计算输出分离到两个单独的表中可能更简单。这也是我想做的事情,它代表了一个比将所有内容都放在一个表中更广泛的用例

我对代码做了一些注释,希望我的逻辑足够清晰。但代码的基本概述如下:

(i) 请求用户输入股票代码(本例中为stock1或stock2)

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

(iii)将库存数据存储在中间数据帧中(如示例1所示)

(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)

尝试将
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

谢谢,在默认情况下,我怀疑用户输入是字符串,这似乎是正确的!我当然可以在这里浮动,而不是在do_pv?股票价格=股票价格。价格是有效的。现在如何修改此代码,以便也可以编辑valn表中的条目?i、 e.我如何修改我的代码,使valn表不受fcff表的驱动,并使我可以向valn表中添加(例如)贴现率,并在valn表中的pv计算中反映其中的任何更改?我已经更新了代码来说明(将r添加到valn表中并使其可编辑)。实际上,我希望fcff和valn表是一个单独的、可编辑的表,可以在编辑时更新计算。