Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/python
- # -*- coding: utf-8 -*-
- import dash
- import dash_core_components as dcc
- import dash_html_components as html
- from dash.dependencies import Input, Output
- import plotly.graph_objs as go
- from datetime import datetime
- import pandas as pd
- import numpy as np
- from sqlalchemy import create_engine
- db_config = {'user': 'my_user',
- 'pwd': '123456',
- 'host': 'localhost',
- 'port': 5432,
- 'db': 'zen'}
- engine = create_engine('postgresql://{}:{}@{}:{}/{}'.format(db_config['user'],
- db_config['pwd'],
- db_config['host'],
- db_config['port'],
- db_config['db']))
- # Формируем строку соединения с БД.
- connection_string = 'postgresql://{}:{}@{}:{}/{}'.format(db_config['user'],
- db_config['pwd'],
- db_config['host'],
- db_config['port'],
- db_config['db'])
- # Подключаемся к БД.
- engine = create_engine(connection_string)
- # получаем данные из таблиц
- query = '''
- SELECT * FROM dash_engagement
- '''
- dash_engagement = pd.io.sql.read_sql(query, con = engine)
- dash_engagement['dt'] = pd.to_datetime(dash_engagement['dt'])
- query = '''
- SELECT * FROM dash_visits
- '''
- dash_visits = pd.io.sql.read_sql(query, con = engine)
- dash_visits['dt'] = pd.to_datetime(dash_visits['dt'])
- note = '''
- Этот дашборд показывает историю игрового рынка (исключая мобильные устройства).
- Используйте выбор интервала даты выпуска, жанра и платформы для управления дашбордом.
- Используйте селектор выбора режима отображения для того, чтобы показать абсолютные
- или относительные значения выпуска и продаж игр по годам.
- '''
- # задаём лейаут
- external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
- app = dash.Dash(__name__, external_stylesheets=external_stylesheets, compress=False)
- app.layout = html.Div(children=[
- # формируем html
- html.H1(children = 'История игрового рынка'),
- html.Br(),
- # пояснения
- html.Label(note),
- html.Br(),
- # здесь начинаeтся ряд с фильтрами
- html.Div([
- # здесь левая сторона ряда (2 фильтра)
- html.Div([
- # фильтр временного периода
- html.Label('Фильтр даты и времени:'),
- dcc.DatePickerRange(
- start_date = dash_visits['dt'].min(),
- end_date = dash_visits['dt'].max(),
- display_format = 'YYYY-MM-DD MM:HH',
- id = 'dt_selector',
- ),
- # здесь фильтр возрастных категорий
- html.Label('Фильтр возрастных категорий:'),
- dcc.Dropdown(
- options = [{'label': x, 'value': x} for x in dash_visits['age_segment'].unique()],
- value = dash_visits['age_segment'].unique().tolist(),
- multi = True,
- id = 'age_dropdown'
- ),
- ], className = 'six columns'),
- # здесь фильтр тем карточек правая сторона ряда)
- html.Div([
- # график истории событий
- html.Label('Фильтр тем карточек:'),
- dcc.Dropdown(
- options = [{'label': x, 'value': x} for x in dash_visits['item_topic'].unique()],
- value = dash_visits['item_topic'].unique().tolist(),
- multi = True,
- id = 'item-topic-dropdown'
- ),
- ], className = 'six columns'),
- # здесь заканчивается ряд с фильтрами
- ], className = 'row'),
- # здесь начинается ряд с графиками
- html.Div([
- # график (левая сторона ряда)
- html.Div([
- # график истории событий
- html.Label('История событий по темам карточек:'),
- dcc.Graph(
- style = {'height': '50vw'},
- id = 'history-absolute-visits'
- ),
- ], className = 'six columns'),
- # графики (правая сторона ряда)
- html.Div([
- html.Br(),
- # график разбивки событий
- html.Label('Разбивка событий по темам источников:'),
- dcc.Graph(
- style = {'height': '25vw'},
- id = 'pie-visits'
- ),
- # график глубины взаимодействия
- html.Label('Глубина взаимодействия:'),
- dcc.Graph(
- style = {'height': '25vw'},
- id = 'engagement-graph'
- ),
- ], className = 'six columns'),
- # здесь заканчивается ряд с графиками
- ], className = 'row'),
- # здесь заканчивается дашборд
- ])
- #описываем логику дашборда
- @app.callback(
- [Output('history-absolute-visits', 'figure'),
- Output('pie-visits', 'figure'),
- Output('engagement-graph', 'figure'),
- ],
- [Input('item-topic-dropdown', 'value'),
- Input('age_dropdown', 'value'),
- Input('dt_selector', 'start_date'),
- Input('dt_selector', 'end_date'),
- ])
- def update_figures(selected_item_topics, selected_ages, start_date, end_date):
- # применяем фильтрацию
- filtered_visits = dash_visits.query('item_topic in @selected_item_topics')
- filtered_visits = filtered_visits.query('age_segment in @selected_ages')
- filtered_visits = filtered_visits.query('dt >= @start_date and dt <= @end_date')
- filtered_engagement = dash_engagement.query('item_topic in @selected_item_topics')
- filtered_engagement = filtered_engagement.query('age_segment in @selected_ages')
- filtered_engagement = filtered_engagement.query('dt >= @start_date and dt <= @end_date')
- # точечная диаграмма
- agg_filtered_visits = filtered_visits.groupby(['item_topic', 'dt']).agg({'visits':'sum'}).reset_index()
- scatterplot = []
- for topic in agg_filtered_visits['item_topic'].unique():
- scatterplot += [go.Scatter(x = agg_filtered_visits.query('item_topic == @topic')['dt'],
- y = agg_filtered_visits.query('item_topic == @topic')['visits'],
- mode = 'lines',
- stackgroup = 'one',
- name = topic)]
- # круговая диаграмма
- agg_filtered_visits_topic = filtered_visits.groupby(['source_topic']).agg({'visits':'sum'}).reset_index()
- pie_chart = [go.Pie(labels = agg_filtered_visits_topic['source_topic'],
- values = agg_filtered_visits_topic['visits'])]
- # столбчатая диаграмма
- agg_engagement = filtered_engagement.groupby('event').agg({'unique_users':'mean'})
- agg_engagement.rename(columns={'unique_users':'avg_unique_users'}, inplace=True)
- bar_chart = [go.Bar(x = agg_filtered_engagement['event'],
- y = agg_filtered_engagement['avg_unique_users'])]
- return (
- {
- 'data': scatterplot,
- 'layout': go.Layout(xaxis = {'title': 'Дата и время'},
- yaxis = {'title': 'Число визитов'})
- },
- {
- 'data': scatterplot,
- 'layout': go.Layout()
- },
- {
- 'data': scatterplot,
- 'layout': go.Layout(xaxis = {'title': 'Событие'},
- yaxis = {'title': 'Число людей'})
- }
- )
- if __name__ == '__main__':
- app.run_server(debug = True, host = '0.0.0.0', port=3000)
Add Comment
Please, Sign In to add comment