Advertisement
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
- from sqlalchemy import create_engine
- db_config = {'user': 'my_user',
- 'pwd': 'my_user_password',
- 'host': 'localhost',
- 'port': 5432,
- 'db': 'zen'}
- 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_visits;
- '''
- dash_visits = pd.io.sql.read_sql(query, con = engine)
- dash_visits['dt'] = pd.to_datetime(dash_visits['dt']).dt.round('min')
- query = '''
- SELECT * FROM dash_engagement;
- '''
- dash_engagement = pd.io.sql.read_sql(query, con = engine)
- dash_engagement['dt'] = pd.to_datetime(dash_engagement['dt']).dt.round('min')
- dash_engagement['all_unique_users'] = dash_engagement['unique_users'].sum()
- note = '''Этот дашборд поможет вам ответить на следующие вопросы:'''
- note1 = '''- Сколько взаимодействий пользователей с карточками происходит в системе с разбивкой по темам карточек?'''
- note2 = '''- Как много карточек генерируют источники с разными темами?'''
- note3 = '''- Насколько хорошо пользователи конвертируются из показов карточек в просмотры статей?'''
- # задаём лейаут
- 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.Label(note),
- html.Br(),
- html.Label(note1),
- html.Label(note2),
- html.Label(note3),
- html.Br(),
- html.Div([
- html.Div([
- # выбор временного периода
- html.H6('Даты:'),
- dcc.DatePickerRange(
- start_date = dash_visits['dt'].dt.date.min(),
- end_date = datetime(2019,9,25).strftime('%Y-%m-%d'),
- display_format = 'YYYY-MM-DD',
- style = {'height': '2vw'},
- id = 'dt_selector',
- ),
- ], className = 'four columns'),
- html.Div([
- # выбор тем карточек
- html.H6('Темы карточек:'),
- dcc.Dropdown(
- options = [{'label': x, 'value': x} for x in dash_visits['item_topic'].unique()],
- value = dash_visits['item_topic'].unique().tolist(),
- multi = True,
- style = {'height': '4vw'},
- id = 'item_topic_dropdown'
- ),
- ], className = 'eight columns'),
- ], className = 'row'),
- html.Div([
- html.Div([
- # выбор возрастных категорий
- html.H6('Возрастные категории:'),
- dcc.Dropdown(
- options = [{'label': x, 'value': x} for x in dash_visits['age_segment'].unique()],
- value = dash_visits['age_segment'].unique().tolist(),
- multi = True,
- style = {'height': '2vw'},
- id = 'age_dropdown'
- ),
- ], className = 'four columns'),
- ], className = 'row'),
- html.Br(),
- html.Br(),
- html.Div([
- html.Div([
- # График событий событий по темам карточек
- html.H4('События по темам карточек:'),
- dcc.Graph(
- style = {'height': '50vw'},
- id = 'history_absolute_visits'
- ),
- ], className = 'six columns'),
- html.Div([
- # График событий по темам источников
- html.H4('События по темам источников:'),
- dcc.Graph(
- style = {'height': '25vw'},
- id = 'pie_visits'
- ),
- # График средней глубины взаимодействия
- html.H4('Средняя глубина взаимодействия:'),
- 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(item_topic_dropdown, age_dropdown, start_date, end_date):
- # применяем фильтрацию и добавляем колонку с долей пользователей в dash_engagement
- dash_visits_filtered_item_topic = dash_visits.query('item_topic.isin(@item_topic_dropdown) and \
- dt >= @start_date and dt <= @end_date \
- and age_segment.isin(@age_dropdown)').groupby(['dt', 'item_topic']).agg({'visits':'sum'}).reset_index()
- dash_visits_filtered_source_topic = dash_visits.query('item_topic.isin(@item_topic_dropdown) and \
- dt >= @start_date and dt <= @end_date \
- and age_segment.isin(@age_dropdown)').groupby(['source_topic']).agg({'visits':'sum'}).reset_index()
- dash_engagement = dash_engagement.query('item_topic.isin(@item_topic_dropdown) and \
- dt >= @start_date and dt <= @end_date \
- and age_segment.isin(@age_dropdown)').groupby(['event', 'all_unique_users']).agg({'unique_users':'sum'}).reset_index()
- dash_engagement['share'] = (dash_engagement['unique_users'] / dash_engagement['all_unique_users']) * 100
- # графики для отображения
- item_topic = [go.Scatter(x = dash_visits_filtered_item_topic['dt'], y = dash_visits_filtered_item_topic['visits'])]
- source_topic = [go.Pie(labels = dash_visits_filtered_source_topic['source_topic'], values = dash_visits_filtered_source_topic['visits'])]
- engagement = [go.Bar(x = dash_engagement['event'], y = dash_engagement['share'])]
- # формируем результат для отображения
- return (
- {
- 'data': item_topic,
- 'layout': go.Layout(xaxis = {'title': 'Даты'},
- yaxis = {'title': 'Количество визитов'})
- },
- {
- 'data': source_topic,
- 'layout': go.Layout()
- },
- {
- 'data': engagement,
- 'layout': go.Layout(xaxis = {'title': 'События'},
- yaxis = {'title': 'Доля'},
- barmode = 'stack')
- }
- )
- if __name__ == '__main__':
- app.run_server(debug = True, host='0.0.0.0')
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement