Изменить ось X на непрерывную неделю года (WK52, WK01 ...) - PullRequest
0 голосов
/ 31 октября 2019

Добрый день,

В настоящее время я создаю Dash-приложение на Python. Цель этого приложения - визуализировать прогнозы и сравнивать их с данными прошлых лет.

Проблема, с которой я сталкиваюсь, заключается в следующем: вместо этого я хотел бы иметь свою ось х в неделю года (начало воскресенья)даты.

До сих пор я пытался создать недельный столбец и использовать его для своих графиков. Проблема в том, что WK01 не будет после WK52, он пойдет в начале моего сюжета, чего я не хочу. В идеале, я хотел бы иметь 10 + недельный горизонт и -10 против сегодняшней даты на моем графике (с WK45 для 2019 и 2018 годов, например).

Мой формат df и фактические значения следующие:

category    date      store    brand    volume  week  year  version
BAG      2019-09-22  LONDON     LV  ...  2428.0   38  2019   FCT
BAG      2019-09-29  LONDON     LV  ...     0.0   39  2019   FCT
BAG      2019-10-06  LONDON     LV  ...     0.0   40  2019   DFT
BAG      2019-10-13  LONDON     LV  ...     0.0   41  2019   FCT
BAG      2019-10-20  LONDON     LV ...     0.0    42  2019   DFT

Вот мой код:

# Import required libraries

import pandas as pd
from flask import Flask
import dash
from dash.dependencies import Input, Output
import dash_core_components as dcc
import dash_html_components as html
import plotly.graph_objs as go
import datetime
from datetime import datetime as dt


app = dash.Dash(__name__)
server = app.server

#Data preparation
df = pd.read_csv('Export.csv')
actuals = pd.read_csv('actuals.csv')
df['date'] = pd.to_datetime(df['date'])
df['year'] = pd.DatetimeIndex(df['date']).year
actuals['date'] = pd.to_datetime(actuals['date'])
actuals['year'] = actuals['date'].dt.year
df['week'] = pd.DatetimeIndex(df['date']).week
actuals['week'] = actuals['date'].dt.week
df = pd.concat([df, actuals])
upperdatelimit = (pd.datetime.today() + pd.to_timedelta(pd.np.ceil(10), unit="W")).strftime('%Y-%m-%d')
lowerdatelimit = (pd.datetime.today() + pd.to_timedelta(pd.np.ceil(-10), unit="W")).strftime('%Y-%m-%d')
mask = (df['date'] <= upperdatelimit) & (df['date'] >= lowerdatelimit)
df = df.loc[mask]

# Create controls
brand_options = [{'label': str(brand), 'value': str(brand)}
                  for brand in df['brand'].unique()]

year_options = [{'label': year,
                        'value': year}
                       for year in actuals['year'].unique()]

store_options = [{'label': str(store), 'value': str(store)}
                       for store in df['store'].unique()]

category_options = [{'label': str(category),
                      'value': str(category)}
                     for category in df['category'].unique()]


# Load data


app.layout = html.Div(
    [
        dcc.Store(id='aggregate_data'),
        html.Div(
            [
                html.Div(
                    [
                        html.H2(
                            'Phantasm',

                        ),
                        html.H4(
                            'Forecast Overview',
                        )
                    ],

                    className='eight columns'
                ),
                html.Img(
                    src="x.png",
                    className='two columns',
                ),
            ],
            id="header",
            className='row',
        ),
        html.Div(
            [
                html.Div(
                    [
                        html.P(
                            'Actuals Comparison Year',
                            className="control_label"
                        ),
                        dcc.Dropdown(
                            id='dropdown',
                            options=year_options,
                            multi=False,
                            value=pd.datetime.today().year - 1,
                            className="dcc_control"
                        ),
                        html.P(
                            'Filter by category:',
                            className="control_label"
                        ),
                        dcc.Dropdown(
                            id='category_names',
                            options=category_options,
                            multi=True,
                            value=list(df['category'].unique()),
                            className="dcc_control"
                        ),
                        html.P(
                            'Filter by brand:',
                            className="control_label"
                        ),
                        dcc.Dropdown(
                            id='brand_names',
                            options=brand_options,
                            multi=True,
                            value=list(df['brand'].unique()),
                            className="dcc_control"
                        ),
                        html.P(
                            'Filter by store:',
                            className="control_label"
                        ),
                        dcc.Dropdown(
                            id='store_names',
                            options=store_options,
                            multi=True,
                            value=list(df['store'].unique()),
                            className="dcc_control"
                        ),
                    ],
                    className="pretty_container four columns"
                ),
                html.Div(
                    [
                        html.Div(
                            [
                                html.Div(
                                    [
                                        html.Div(
                                            [
                                                html.P("Hermes"),
                                                html.H6(
                                                    id="brand_text",
                                                    className="info_text"
                                                )
                                            ],
                                            id="Hermes",
                                            className="pretty_container"
                                        ),
                                        html.Div(
                                            [
                                                html.P("LV"),
                                                html.H6(
                                                    id="branda_text",
                                                    className="info_text"
                                                )
                                            ],
                                            id="LV",
                                            className="pretty_container"
                                        ),
                                        html.Div(
                                            [
                                                html.P("Valentino"),
                                                html.H6(
                                                    id="brandb_text",
                                                    className="info_text"
                                                )
                                            ],
                                            id="valentino",
                                            className="pretty_container"
                                        ),
                                    ],
                                    id="tripleContainer",
                                )

                            ],
                            id="infoContainer",
                            className="row"
                        ),
                        html.Div(
                            [
                                dcc.Graph(
                                    id='count_graph',
                                )
                            ],
                            id="countGraphContainer",
                            className="pretty_container"
                        )
                    ],
                    id="rightCol",
                    className="eight columns"
                )
            ],
            className="row"
        ),
        html.Div(
            [
                html.Div(
                    [
                        dcc.Graph(id='main_graph')
                    ],
                    className='pretty_container eight columns',
                ),
                html.Div(
                    [
                        dcc.Graph(id='individual_graph')
                    ],
                    className='pretty_container four columns',
                ),
            ],
            className='row'
        ),
        html.Div(
            [
                html.Div(
                    [
                        dcc.Graph(id='pie_graph')
                    ],
                    className='pretty_container seven columns',
                ),
                html.Div(
                    [
                        dcc.Graph(id='aggregate_graph')
                    ],
                    className='pretty_container five columns',
                ),
            ],
            className='row'
        ),
    ],
    id="mainContainer",
    style={
        "display": "flex",
        "flex-direction": "column"
    }
)


# Create callbacks

@app.callback(Output('brand_text', 'children'),
              [Input('store_names', 'value'),
               Input('category_names', 'value')])
def update_forecast_text(store_names,category_names):
    dff = df[df['store'].isin(store_names) & df['category'].isin(category_names)
             & df['brand'].isin(['Hermes']) & df['version'].isin(['DFT'])]
    return ""+"{:,}".format(int(dff['volume'].sum()))

@app.callback(Output('branda_text', 'children'),
              [Input('store_names', 'value'),
               Input('category_names', 'value')])
def update_forecast_text(store_names,category_names):
    dff = df[df['store'].isin(store_names) & df['category'].isin(category_names)
             & df['brand'].isin(['LV']) & df['version'].isin(['DFT'])]
    return ""+"{:,}".format(int(dff['volume'].sum()))

@app.callback(Output('brandb_text', 'children'),
              [Input('store_names', 'value'),
               Input('category_names', 'value')])
def update_forecast_text(store_names,category_names):
    dff = df[df['store'].isin(store_names) & df['category'].isin(category_names)
             & df['brand'].isin(['Valentino']) & df['version'].isin(['DFT'])]
    return ""+"{:,}".format(int(dff['volume'].sum()))

@app.callback(Output('main_graph', 'figure'),
              [Input('dropdown', 'value'),
               Input('store_names', 'value'),
               Input('category_names', 'value'),
               Input('brand_names','value')])
def update_graph(dropdown_value,store_names,category_names,brand_names):
    actualsdf = actuals[actuals['year'] == dropdown_value]
    dffdraft = df[df['store'].isin(store_names) & df['category'].isin(category_names)
             & df['brand'].isin(brand_names) & df['version'].isin(['DFT','ACTUALS'])]
    dfffct = df[df['store'].isin(store_names) & df['category'].isin(category_names)
             & df['brand'].isin(brand_names) & df['version'].isin(['FCT','ACTUALS'])]
    dffactuals = actualsdf[actualsdf['store'].isin(store_names) & actualsdf['category'].isin(category_names)
                           & actualsdf['brand'].isin(brand_names) & actualsdf['version'].isin(['ACTUALS'])]
    dffdraft = dffdraft.groupby('date')['volume'].sum().reset_index()
    dfffct = dfffct.groupby('date')['volume'].sum().reset_index()
    dffactuals = dffactuals.groupby('date')['volume'].sum().reset_index()
    trace1 = go.Scatter(y=dffdraft['volume'],x=dffdraft['date'],mode='lines',name='Draft')
    trace2 = go.Scatter(y=dfffct['volume'], x=dfffct['date'], mode='lines', name='Forecast')
    trace3 = go.Scatter(y=dffactuals['volume'], x=dffactuals['date'], mode='lines', name='Actuals')
    data = [trace1,trace2,trace3]
    return {"data": data}

# Main
if __name__ == '__main__':
    app.server.run(debug=True, threaded=True)

Большое спасибо!

Цель

Токовый выход

1 Ответ

0 голосов
/ 01 ноября 2019

Один из способов решения этой проблемы - использовать столбец даты в качестве значения x для вашего графика, а затем установить формат отметки:

return {"data": data, "layout": {"xaxis": {"tickformat": "W%W"}}}

Вот документация и пример и здесь форматы даты .

Если это не соответствует вашим потребностям, у вас всегда есть выбор: использовать собственные позиции и метки. Это больше работы, но она полностью настраивается. Вот пример .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...