Advertisement
Guest User

Untitled

a guest
Feb 21st, 2020
96
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 8.85 KB | None | 0 0
  1. ##!/usr/bin/python
  2. # -*- coding: utf-8 -*-
  3.  
  4. import dash
  5. import dash_core_components as dcc
  6. import dash_html_components as html
  7. from dash.dependencies import Input, Output
  8. from datetime import datetime as dt
  9.  
  10. import plotly.graph_objs as go
  11.  
  12. import pandas as pd
  13.  
  14. from sqlalchemy import create_engine
  15.  
  16. engine = create_engine('sqlite:////db/zen.db', echo = False)
  17.  
  18. db_config = {'user': 'my_user',
  19.             'pwd': 'my_user_password',
  20.             'host': 'localhost',
  21.             'port': 5432,
  22.             'db': 'zen'}
  23. engine = create_engine('postgresql://{}:{}@{}:{}/{}'.format(db_config['user'],
  24.                                                            db_config['pwd'],
  25.                                                            db_config['host'],
  26.                                                            db_config['port'],
  27.                                                            db_config['db']))
  28.  
  29. #получаем сырые данные
  30. query_visits = '''
  31.           SELECT * FROM dash_visits
  32.       '''
  33. dash_visits = pd.io.sql.read_sql(query_visits, con = engine)
  34.  
  35. dash_visits['dt'] = pd.to_datetime(dash_visits['dt'])
  36.  
  37. query_engagement = '''
  38.           SELECT * FROM dash_engagement
  39.       '''
  40. dash_engagement = pd.io.sql.read_sql(query_engagement, con = engine)
  41. dash_engagement['dt'] = pd.to_datetime(dash_engagement['dt'])
  42.  
  43.  
  44. note = '''
  45.         Этот дашборд показывает историю взаимодействия пользователей с карточками в Яндекс.Дзене.
  46.         Используйте выбор интервала даты событий, тем карточек и возрастных категорий для управления дашбордом.
  47.      '''
  48. #задаём лейаут
  49. external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
  50. app = dash.Dash(__name__, external_stylesheets = external_stylesheets)
  51. app.layout = html.Div(children=[  
  52.  
  53.     #заголовок
  54.     html.H1(children = 'Метрики Яндекс.Дзен'),    
  55.  
  56.     html.Br(),  
  57.     html.Label(note),
  58.  
  59.     html.Br(),        
  60.  
  61.     html.Div([
  62.         html.Div([
  63.             html.Div([
  64.             #выбор временного периода
  65.                 html.Label('Фильтр даты'),
  66.                     dcc.DatePickerRange(
  67.                         start_date = dash_visits['dt'].dt.date.min(),
  68.                         end_date = dt(2019,9,24).strftime('%Y-%m-%d'),
  69.                         display_format = 'YYYY-MM-DD',
  70.                         id = 'dt_selector',
  71.                         ),
  72.                     ], className = 'row container-display'),          
  73.        
  74.             html.Div([
  75.             #выбор возраста
  76.                 html.Label('Фильтр возрастных категорий'),
  77.                     dcc.Dropdown(
  78.                         options = [{'label': x, 'value': x} for x in dash_visits['age_segment'].unique()],
  79.                         value = dash_visits['age_segment'].unique(),
  80.                         multi = True,
  81.                         id = 'age-dropdown',
  82.                         ),
  83.                     ], className = 'row container-display'),
  84.             ], className = 'six columns'
  85.             ),
  86.        
  87.             html.Div([
  88.             #выбор тем карточек    
  89.                 html.Label('Фильтр тем карточек'),
  90.                     dcc.Dropdown(
  91.                         options = [{'label': x, 'value': x} for x in dash_visits['item_topic'].unique()],
  92.                         value = dash_visits['item_topic'].unique(),
  93.                         multi = True,
  94.                         id = 'item-topic-dropdown',
  95.                         style = {'height':'50%'}
  96.                         ),
  97.                 ], className = 'six columns'),
  98.             ], className = 'row'),
  99.  
  100.     # блоки для графиков
  101.    
  102.     html.Div([
  103.         html.Div([        
  104.             html.Label('История событий по темам карточек'),
  105.             dcc.Graph(
  106.                 id = 'history-absolute-visits',
  107.                 style = {'height': '50vw'},
  108.                 ),  
  109.             ], className = 'six columns'),  
  110.  
  111.         html.Div([        
  112.             html.Label('События по темам источников'),
  113.             dcc.Graph(
  114.                 id = 'pie-visits',
  115.                 style = {'height': '25vw'},
  116.             ),  
  117.             html.Label('Средняя глубина взаимодействия'),
  118.             dcc.Graph(
  119.                 id = 'engagement-graph',
  120.                 style = {'height': '25vw'},
  121.             ),  
  122.             ], className = 'six columns')            
  123.         ], className = 'row')
  124. ])
  125.  
  126. #описываем логику дашборда
  127. @app.callback(
  128.     [Output('history-absolute-visits', 'figure'),
  129.     Output('pie-visits', 'figure'),
  130.     Output('engagement-graph', 'figure')],
  131.     [Input('item-topic-dropdown', 'value'),
  132.     Input('age-dropdown', 'value'),
  133.     Input('dt_selector', 'start_date'),
  134.     Input('dt_selector', 'end_date'),
  135.     ])
  136.  
  137. def update_figures(selected_item_topics, selected_ages, start_date, end_date):
  138.  
  139.     start_date = dt.strptime(start_date, '%Y-%m-%d')
  140.     end_date = dt.strptime(end_date, '%Y-%m-%d')
  141.  
  142.     #применяем фильтрацию
  143.     visits_filtered = dash_visits.query('item_topic.isin(@selected_item_topics) and dt >= @start_date and dt <= @end_date and age_segment.isin(@selected_ages)')
  144.  
  145.     engagement_filtered = dash_engagement.query('item_topic.isin(@selected_item_topics) and dt >= @start_date and dt <= @end_date and age_segment.isin(@selected_ages)')
  146.    
  147.     #данные для графиков
  148.     visits_by_item_topic = (visits_filtered.groupby(['item_topic','dt'])
  149.                                            .agg({'visits' : 'sum'})
  150.                                            .sort_values(by = 'visits', ascending = False)
  151.                                            .reset_index())
  152.                                
  153.     visits_by_source_topic = (visits_filtered.groupby('source_topic')
  154.                                              .agg({'visits' : 'sum'})
  155.                                              .reset_index())
  156.  
  157.     engagement = (engagement_filtered.groupby('event')
  158.                                      .agg({'unique_users' : 'mean'})
  159.                                      .rename(columns = {'unique_users' : 'avg_unique_users'})
  160.                                      .sort_values(by = 'avg_unique_users', ascending = False)
  161.                                      .reset_index())
  162.    
  163.     data_item_topic_dropdown = []
  164.    
  165.     #график истории событий по темам карточек
  166.     for item in visits_by_item_topic['item_topic'].unique():
  167.         current = visits_by_item_topic[visits_by_item_topic['item_topic'] == item]
  168.         data_item_topic_dropdown += [go.Scatter(x = current['dt'],
  169.                                    y = current['visits'],
  170.                                    mode = 'lines',
  171.                                    stackgroup = 'one',
  172.                                    name = item)
  173.                         ]
  174.                        
  175.     #график разбивки событий по темам источников
  176.     data_pie_source_topic = [go.Pie(labels = visits_by_source_topic['source_topic'],
  177.                                     values = visits_by_source_topic['visits'])
  178.  
  179.                         ]
  180.                          
  181.     #график средней глубины взаимодействия
  182.     data_engagement_graph = [go.Bar(x = engagement['event'],
  183.                                    y = engagement['avg_unique_users'],
  184.                                    name = 'Среднее количество уникальных пользователей')
  185.                         ]
  186.    
  187.    
  188.  
  189.     return (
  190.             #график item-topic
  191.             {
  192.                 'data': data_item_topic_dropdown,
  193.                 'layout': go.Layout(xaxis = {'title': 'Время'},
  194.                                     yaxis = {'title': 'Количество событий'})
  195.             },    
  196.            
  197.             #график pie-visits
  198.             {
  199.                 'data': data_pie_source_topic,
  200.                 'layout': go.Layout()
  201.             },
  202.            
  203.             #график engagement-graph
  204.             {
  205.                 'data': data_engagement_graph,
  206.                 'layout': go.Layout(xaxis = {'title': 'Тип cобытия'},
  207.                                     yaxis = {'title': 'Среднее число уникальных пользователей'},
  208.                                     hovermode = 'closest')
  209.              },
  210.          )            
  211.  
  212. if __name__ == '__main__':
  213.     app.run_server(debug=True, host='0.0.0.0')
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement