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'])
- query = '''
- SELECT * FROM dash_engagement
- '''
- dash_engagement = pd.io.sql.read_sql(query, con = engine)
- dash_engagement['dt'] = pd.to_datetime(dash_engagement['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.Div([
- html.Div([
- # график истории событий по темам карточек
- html.Label('История событий по темам карточек:'),
- dcc.Graph(
- id = 'history-absolute-visits'
- ),
- ], className = 'six columns'),
- html.Div([
- # график событий по темам источников
- html.Label('Разбивка всех событий по темам источников:'),
- dcc.Graph(
- id = 'pie-visits'
- ),
- ], className = 'six columns'),
- ], className = 'row'),
- html.Div([
- html.Div([
- # воронка уникадльных показов
- html.Label('Усредненная воронка уникальных показов:'),
- dcc.Graph(
- id = 'engagement-graph'
- ),
- ], className = 'six columns'),
- ], className = 'row'),
- # пояснения
- html.Label(note),
- html.Br(),
- html.Div([
- 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 = 'eight columns'),
- html.Div([
- # выбор возрастной группы
- 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 = 'two columns'),
- html.Div([
- # выбор временного периода
- html.Label('Года выпуска:'),
- dcc.DatePickerRange(
- start_date = dash_visits['dt'].dt.date.min(),
- end_date = dash_visits['dt'].dt.date.max(),
- display_format = 'YYYY-MM-DD',
- id = 'dt_selector',
- ),
- ], className = 'two columns'),
- ], className = 'row'),
- ])
- #описываем логику дашборда
- @app.callback(
- [Output('history-absolute-visits', 'figure'),
- Output('pie-visits', 'figure'),
- Output('engagement-graph', 'figure'),
- ],
- [Input('dt_selector', 'start_date'),
- Input('dt_selector', 'end_date'),
- Input('age-dropdown', 'value'),
- Input('item-topic-dropdown', 'value'),
- ])
- def update_figures(start_date, end_date, selected_age, selected_topic):
- #применяем фильтрацию
- filtered_visits = dash_visits.query('dt >= @start_date and dt <= @end_date')
- filtered_visits = filtered.query('age_segment in @selected_age')
- filtered_visits = filtered.query('item_topic in @selected_topic')
- filtered_engagement = dash_engagement.query('dt >= @start_date and dt <= @end_date')
- filtered_engagement = filtered.query('age_segment in @selected_age')
- filtered_engagement = filtered.query('item_topic in @selected_topic')
- visits_by_item = (filtered_visits.groupby(['dt', 'item_topic'])
- .agg({'visits': 'sum'})
- .reset_index()
- )
- visits_by_source = (filtered_visits.groupby(['source_topic'])
- .agg({'visits': 'sum'})
- .reset_index()
- )
- engagement = (filtered_engagement.groupby(['event'])
- .agg({'unique_users':'mean'})
- .reset_index()
- )
- engagement['relative_n'] = engagement['unique_users'] / engagement[engagement['event'] == '']['unique_users']
- # график
- data_by_item = []
- for item_topic in dash_visits['item_topic'].unique():
- data_by_item += [go.Scatter(x = visits_by_item.query('item_topic == @item_topic')['dt'],
- y = visits_by_item.query('item_topic == @item_topic')['visits'],
- mode = 'lines',
- stackgroup = 'one',
- name = item_topic)]
- # график
- data_by_source = [go.Pie(labels = visits_by_source['source_topic'],
- values = visits_by_source['visits'],
- name = 'source_topic')]
- # столбчатая диаграмма уникальных показов
- data_engagement = [go.Bar(x = engagement.query('item_topic == @item_topic')['event'],
- y = engagement.query('item_topic == @item_topic')['unique_users'],
- barmode='relative',
- name = 'event')]
- #формируем результат для отображения
- return (
- {
- 'data': data_by_item,
- 'layout': go.Layout(xaxis = {'title': 'Год'},
- yaxis = {'title': 'Количество событий'})
- },
- {
- 'data': data_by_source,
- 'layout': go.Layout()
- },
- {
- 'data': data_engagement,
- 'layout': go.Layout(xaxis = {'title': 'Тип события'},
- yaxis = {'title': 'Среднее количество событий в % от показов'})
- },
- )
- if __name__ == '__main__':
- app.run_server(host='0.0.0.0', port=3000)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement