Advertisement
solaris0909

Untitled

Feb 25th, 2020
168
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 7.14 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.  
  9. import plotly.graph_objs as go
  10.  
  11. from datetime import datetime
  12. import numpy as np
  13. import pandas as pd
  14.  
  15. # задаём данные для отрисовки
  16. from sqlalchemy import create_engine
  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. query_visits = '''
  30. SELECT * FROM dash_visits
  31. '''
  32.  
  33. query_engagement = '''
  34. SELECT * FROM dash_engagement
  35. '''
  36. # записываем их в таблицу
  37. dash_visits = pd.io.sql.read_sql(query_visits, con = engine)
  38. dash_engagement = pd.io.sql.read_sql(query_engagement, con = engine)
  39.  
  40. # приводим тип данных в dt
  41. dash_visits['dt'] = pd.to_datetime(dash_visits['dt'])
  42. dash_engagement['dt'] = pd.to_datetime(dash_engagement['dt'])
  43.  
  44. age_groups = dash_visits['age_segment'].unique()
  45.  
  46. note = '''
  47. Дашборд по визитам и вовлечённости пользователей.
  48. '''
  49.  
  50. external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
  51. app = dash.Dash(__name__, external_stylesheets=external_stylesheets,compress=False)
  52. app.config['suppress_callback_exceptions'] = False
  53.  
  54. app.layout = html.Div(children=[
  55. # формируем html
  56. html.H1(children = 'Дашборд для Яндекс.Дзена'),
  57. # пояснения
  58. html.Label(note),
  59. html.Br(),
  60.  
  61. # вывод фильтров и селекторов
  62. html.Div([
  63. html.Div([
  64. html.Label('Фильтр даты и времени:'),
  65. dcc.DatePickerRange(
  66. start_date = dash_visits['dt'].min(),
  67. end_date = dash_visits['dt'].max(),
  68. display_format = 'YYYY-MM-DD MM:HH',
  69. id = 'dt_selector',
  70. ),
  71.  
  72. html.Label('Фильтр возрастных категорий:'),
  73. dcc.Dropdown(
  74. options = [{'label': x, 'value': x} for x in dash_visits['age_segment'].unique()],
  75. value = dash_visits['age_segment'].unique().tolist(),
  76. multi = True,
  77. id = 'age_dropdown',
  78. ),
  79. ], className = 'six columns'),
  80.  
  81. html.Div([
  82. html.Label('Фильтр тем карточек:'),
  83. dcc.Dropdown(
  84. options = [{'label': x, 'value': x} for x in dash_visits['item_topic'].unique()],
  85. value = dash_visits['item_topic'].unique().tolist(),
  86. multi = True,
  87. id = 'item_topic_dropdown',
  88. ),
  89. ], className = 'six columns')
  90. ], className = 'row'),
  91.  
  92. # отрисовка графиков
  93. html.Div([
  94. html.Div([
  95. # график разбивки событий по темам источников
  96. html.Label('График событий во времени:'),
  97. dcc.Graph(
  98. style = {'height': '50vw'},
  99. id = 'history_absolute_visits'
  100. ),
  101. ], className = 'six columns'),
  102.  
  103. html.Div([
  104. # график средней глубины взаимодействия
  105. html.Label('Круговая диаграмма событий:'),
  106. dcc.Graph(
  107. style = {'height': '25vw'},
  108. id = 'pie_visits'
  109. ),
  110.  
  111. # график истории событий по темам карточек
  112. html.Label('Столбчатая диаграмма глубины взаимодействия:'),
  113. dcc.Graph(
  114. style = {'height': '25vw'},
  115. id = 'engagement_graph'
  116. ),
  117. ], className = 'six columns'),
  118. ], className = 'row'),
  119.  
  120. ]) # начинается на Div(children=
  121.  
  122. @app.callback(
  123. [Output('history_absolute_visits', 'figure'),
  124. Output('pie_visits', 'figure'),
  125. Output('engagement_graph', 'figure')],
  126. [Input('item_topic_dropdown', 'value'),
  127. Input('age_dropdown', 'value'),
  128. Input('dt_selector', 'start_date'),
  129. Input('dt_selector', 'end_date')]
  130. )
  131.  
  132. def update_figures(selected_item_topics, selected_ages, start_date, end_date):
  133. query_filter = 'item_topic.isin(@selected_item_topics) and \
  134. dt >= @start_date and dt <= @end_date \
  135. and age_segment.isin(@selected_ages)'
  136.  
  137. filtered_visits = dash_visits.query(query_filter)
  138. filtered_engagement = dash_engagement.query(query_filter)
  139.  
  140. # точечная диаграмма
  141. agg_filtered_visits = filtered_visits.groupby(['item_topic', 'dt'], asindex=False).agg({'visits': 'sum'})
  142. scatterplot = []
  143. for topic in agg_filtered_visits['item_topic'].unique():
  144. scatterplot += [go.Scatter(x = agg_filtered_visits.query('item_topic == @topic')['dt'],
  145. y = agg_filtered_visits.query('item_topic == @topic')['visits'],
  146. mode = 'lines',
  147. stackgroup = 'one',
  148. name = topic)]
  149.  
  150. # круговая диаграмма
  151. agg_filtered_visits_topic = filtered_visits.groupby('source_topic', asindex=False).agg({'visits': 'sum'})
  152. pie_by_topic = [go.Pie(labels = agg_filtered_visits_topic['source_topic'],
  153. values = agg_filtered_visits_topic['visits'])]
  154.  
  155. # столбчатая диаграмма
  156. agg_filtered_engagement = filtered_engagement.groupby('event', asindex=False).agg({'unique_users':'mean'})
  157. agg_filtered_engagement.rename(columns={'unique_users':'avg_unique_users'}, inplace=True)
  158. bar_by_event = go.Bar(x = report['event'],
  159. y = report['avg_unique_users'])
  160.  
  161. # формируем результат для отображения
  162. return (
  163. {
  164. 'data': scatterplot,
  165. 'layout': go.Layout(xaxis={'title': 'Дата и время'},
  166. yaxis={'title': 'Визиты'})
  167. },
  168. {
  169. 'data': pie_by_topic,
  170. 'layout': go.Layout()
  171. },
  172. {
  173. 'data': bar_by_event,
  174. 'layout': go.Layout(xaxis={'title': 'Событие'},
  175. yaxis={'title': 'Среднее кол-во уников'})
  176. },
  177. )
  178. # описываем логику дашборда
  179. if __name__ == '__main__':
  180. app.run_server(debug = True, host='0.0.0.0')
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement