【问题标题】:Plotly Dash: How to display a calculated value from a data frame created from a file upload?Plotly Dash:如何显示从文件上传创建的数据框中的计算值?
【发布时间】:2020-06-11 17:18:22
【问题描述】:

我在Pandas 数据框中有以下数据:

     df = pd.DataFrame({'Make':['Mercedes', 'BMW', 'Mercedes', 'Mercedes', 'Chrysler', 'Chrysler', 'Chrysler', 'Chrysler', 'BMW', 'Chrysler', 'BMW', 'Mercedes', 'BMW', 'Mercedes'],
                          'Dimension':['Styling', 'Styling', 'Price', 'Styling', 'MPG', 'MPG', 'Styling', 'Styling', 'MPG', 'MPG', 'Price', 'Price', 'Styling', 'MPG'],
                          'Country':['USA', 'USA', 'USA', 'Germany', 'USA', 'USA', 'USA', 'England', 'Germany', 'USA', 'Germany', 'Poland', 'Italy', 'USA'],
                          'LowValue':['64', '61', '70', '65', '59', '68', '63', '57', '58', '55', '69', '63', '69', '61'],
                          'HighValue':['82', '95', '93', '95', '87', '93', '85', '85', '95', '92', '83', '87', '80', '80']})

我正在使用Plotly Dash 框架构建一个Web 应用程序。该应用程序允许用户上传文件并在屏幕上呈现内容。我想显示一些关于在文件上传时创建的 Pandas 数据框的摘要统计信息。

这里是上传文件和渲染应用的代码:

import base64
import dash
from dash.dependencies import Input, Output, State
import dash_html_components as html
import dash_core_components as dcc
import dash_table
import datetime
from datetime import datetime as dt
import io
import os
import pandas as pd
import re


# initialize the application
app = dash.Dash()

# define the layout of the app
app.layout = html.Div([

    html.Div([
        dcc.Upload(
            id='upload-data',
            children=html.Div([
                'Drag and Drop or ',
                html.A('Select Files')
            ]),
            style={
            'width' : '50%',
            'height' : '60px',
            'lineHeight' : '60px',
            'borderWidth' : '1px',
            'borderStyle' : 'dashed',
            'borderRadius' : '5px',
            'textAlign' : 'center',
            'marginTop' : '10px',
            'marginRight' : '10px',
            'marginBottom' : '50px',
            'marginLeft' : '300px',
            'color' : '#87ceeb'
            },
            multiple=True
            ),
        html.Div(id='output-data-upload'),
        ]),

])


def parse_contents(contents, filename, date):
    content_type, content_string = contents.split(',')

    decoded = base64.b64decode(content_string)
    try:
        if 'csv' in filename:
            # assume that the user uploaded a CSV file
            df = pd.read_csv(
                io.StringIO(decoded.decode('utf-8')))
        elif 'xls' in filename:
            # assume that the user uploaded an Excel file
            df = pd.read_excel(io.BytesIO(decoded))
        elif 'txt' or 'tsv' in filename:
            # assume that the user uploaded a TXT file
            df = pd.read_csv(io.StringIO(decoded.decode('utf-8')), delimiter = r'\s+')
    except Exception as e:
        print(e)
        return html.Div([
            'There was an error processing this file.'
            ])

    # transform the original data frame to get the average of low value for Styling
    df_new = df[(df['Dimension'] == 'Styling')]
    df_new['LowValue'] = pd.to_numeric(df_new['LowValue'])
    mean_of_low_value = df_new['LowValue'].mean()

    return html.Div([
        html.H5(filename),
        html.H6(datetime.datetime.fromtimestamp(date)),

        dash_table.DataTable(
            id='table',
            columns=[{'name': i, 'id': i} for i in df.columns],
            data=df.to_dict('records'),
            sort_action='native',
            filter_action='native',
            page_size= 5,
            style_table={'height' : '300px',
                         'overflowY' : 'auto'},
            style_cell={'width' : '300px',
                        'height' : '30px',
                        'textAlign' : 'left'}
            ),

])



@app.callback(Output('output-data-upload', 'children'),
    [Input('upload-data', 'contents')],
    [State('upload-data', 'filename'),
     State('upload-data', 'last_modified')])
def update_output(list_of_contents, list_of_names, list_of_dates):
    if list_of_contents is not None:
        children = [
            parse_contents(c, n, d) for c, n, d in
            zip(list_of_contents, list_of_names, list_of_dates)]
        return children


if __name__ == '__main__':
    app.run_server(debug = True, use_reloader=True)

上传文件时会创建一个df 对象。然后我操纵df 来获得StylingLow 分数的平均值。

使用这个数据集,mean_of_low_value variable 是 63.1666。

问题:如何在屏幕上显示以下内容?

"Styling 平均分:63.1666"

提前致谢!

【问题讨论】:

    标签: python pandas plotly plotly-dash


    【解决方案1】:

    您可以创建一个新组件(例如html.Div()html.H1()html.P() 等),然后在children 属性中包含转换为字符串的文本和数值,例如作为

    html.Div(children=['The average Styling score is: ' + str(mean_of_low_value)]),
    

    或者如果你想将值四舍五入(假设为 2 位)

    html.Div(children=['The average (rounded) Styling score is: ' + format(mean_of_low_value, '.2f')]
    

    我更新了您的代码(复制如下)以包含上述两个示例。

    import base64
    import dash
    from dash.dependencies import Input, Output, State
    import dash_html_components as html
    import dash_core_components as dcc
    import dash_table
    import datetime
    from datetime import datetime as dt
    import io
    import os
    import pandas as pd
    import re
    
    # initialize the application
    app = dash.Dash()
    
    # define the layout of the app
    app.layout = html.Div([
    
        html.Div([
            dcc.Upload(
                id='upload-data',
                children=html.Div([
                    'Drag and Drop or ',
                    html.A('Select Files')
                ]),
                style={
                'width' : '50%',
                'height' : '60px',
                'lineHeight' : '60px',
                'borderWidth' : '1px',
                'borderStyle' : 'dashed',
                'borderRadius' : '5px',
                'textAlign' : 'center',
                'marginTop' : '10px',
                'marginRight' : '10px',
                'marginBottom' : '50px',
                'marginLeft' : '300px',
                'color' : '#87ceeb'
                },
                multiple=True
                ),
            html.Div(id='output-data-upload'),
            ]),
    
    ])
    
    
    def parse_contents(contents, filename, date):
    
        content_type, content_string = contents.split(',')
    
        decoded = base64.b64decode(content_string)
        try:
            if 'csv' in filename:
                # assume that the user uploaded a CSV file
                df = pd.read_csv(
                    io.StringIO(decoded.decode('utf-8')))
            elif 'xls' in filename:
                # assume that the user uploaded an Excel file
                df = pd.read_excel(io.BytesIO(decoded))
            elif 'txt' or 'tsv' in filename:
                # assume that the user uploaded a TXT file
                df = pd.read_csv(io.StringIO(decoded.decode('utf-8')), delimiter = r'\s+')
        except Exception as e:
            print(e)
            return html.Div([
                'There was an error processing this file.'
                ])
    
        # transform the original data frame to get the average of low value for Styling
        df_new = df[(df['Dimension'] == 'Styling')]
        df_new['LowValue'] = pd.to_numeric(df_new['LowValue'])
        mean_of_low_value = df_new['LowValue'].mean()
    
        return html.Div([
    
            html.H5(filename),
            html.H6(datetime.datetime.fromtimestamp(date)),
    
            dash_table.DataTable(
                id='table',
                columns=[{'name': i, 'id': i} for i in df.columns],
                data=df.to_dict('records'),
                sort_action='native',
                filter_action='native',
                page_size= 5,
                style_table={'height' : '300px',
                             'overflowY' : 'auto'},
                style_cell={'width' : '300px',
                            'height' : '30px',
                            'textAlign' : 'left'}
                ),
    
            html.Div(children=['The average Styling score is: ' + str(mean_of_low_value)]),
    
            html.Div(children=['The average (rounded) Styling score is: ' + format(mean_of_low_value, '.2f')]),
    
    ])
    
    
    @app.callback(Output('output-data-upload', 'children'),
        [Input('upload-data', 'contents')],
        [State('upload-data', 'filename'),
         State('upload-data', 'last_modified')])
    def update_output(list_of_contents, list_of_names, list_of_dates):
        if list_of_contents is not None:
            children = [
                parse_contents(c, n, d) for c, n, d in
                zip(list_of_contents, list_of_names, list_of_dates)]
            return children
    
    
    if __name__ == '__main__':
        app.run_server(debug = True, use_reloader=True)
    

    【讨论】:

    • 谢谢你,@gflavia!我不知道可以在children 属性中“嵌入”计算。您的解决方案不仅解决了这个问题,而且还解决了其他一些问题!再次感谢!
    猜你喜欢
    • 2019-11-04
    • 1970-01-01
    • 1970-01-01
    • 2019-05-16
    • 2019-06-25
    • 2022-01-16
    • 2021-02-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多