mironovichandrei

Untitled

Feb 29th, 2020
63
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.12 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.  
  13. import pandas as pd
  14.  
  15. import numpy as np
  16.  
  17. from sqlalchemy import create_engine
  18.  
  19. db_config = {'user': 'my_user',
  20. 'pwd': '123456',
  21. 'host': 'localhost',
  22. 'port': 5432,
  23. 'db': 'zen'}
  24. engine = create_engine('postgresql://{}:{}@{}:{}/{}'.format(db_config['user'],
  25. db_config['pwd'],
  26. db_config['host'],
  27. db_config['port'],
  28. db_config['db']))
  29. # Формируем строку соединения с БД.
  30. connection_string = 'postgresql://{}:{}@{}:{}/{}'.format(db_config['user'],
  31. db_config['pwd'],
  32. db_config['host'],
  33. db_config['port'],
  34. db_config['db'])
  35.  
  36. # Подключаемся к БД.
  37. engine = create_engine(connection_string)
  38.  
  39. # получаем данные из таблиц
  40. query = '''
  41. SELECT * FROM dash_engagement
  42. '''
  43. dash_engagement = pd.io.sql.read_sql(query, con = engine)
  44. dash_engagement['dt'] = pd.to_datetime(dash_engagement['dt'])
  45.  
  46. query = '''
  47. SELECT * FROM dash_visits
  48. '''
  49. dash_visits = pd.io.sql.read_sql(query, con = engine)
  50. dash_visits['dt'] = pd.to_datetime(dash_visits['dt'])
  51.  
  52. note = '''
  53. Этот дашборд показывает историю игрового рынка (исключая мобильные устройства).
  54. Используйте выбор интервала даты выпуска, жанра и платформы для управления дашбордом.
  55. Используйте селектор выбора режима отображения для того, чтобы показать абсолютные
  56. или относительные значения выпуска и продаж игр по годам.
  57. '''
  58.  
  59. # задаём лейаут
  60. external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
  61. app = dash.Dash(__name__, external_stylesheets=external_stylesheets, compress=False)
  62. app.layout = html.Div(children=[
  63.  
  64. # формируем html
  65. html.H1(children = 'История игрового рынка'),
  66.  
  67. html.Br(),
  68.  
  69. # пояснения
  70. html.Label(note),
  71.  
  72. html.Br(),
  73.  
  74. # здесь начинаeтся ряд с фильтрами
  75.  
  76. html.Div([
  77.  
  78. # здесь левая сторона ряда (2 фильтра)
  79. html.Div([
  80.  
  81. # фильтр временного периода
  82. html.Label('Фильтр даты и времени:'),
  83. dcc.DatePickerRange(
  84. start_date = dash_visits['dt'].min(),
  85. end_date = dash_visits['dt'].max(),
  86. display_format = 'YYYY-MM-DD MM:HH',
  87. id = 'dt_selector',
  88. ),
  89.  
  90. # здесь фильтр возрастных категорий
  91.  
  92. html.Label('Фильтр возрастных категорий:'),
  93. dcc.Dropdown(
  94. options = [{'label': x, 'value': x} for x in dash_visits['age_segment'].unique()],
  95. value = dash_visits['age_segment'].unique().tolist(),
  96. multi = True,
  97. id = 'age_dropdown'
  98. ),
  99.  
  100. ], className = 'six columns'),
  101.  
  102. # здесь фильтр тем карточек правая сторона ряда)
  103. html.Div([
  104.  
  105. # график истории событий
  106. html.Label('Фильтр тем карточек:'),
  107. dcc.Dropdown(
  108. options = [{'label': x, 'value': x} for x in dash_visits['item_topic'].unique()],
  109. value = dash_visits['item_topic'].unique().tolist(),
  110. multi = True,
  111. id = 'item-topic-dropdown'
  112. ),
  113. ], className = 'six columns'),
  114.  
  115. # здесь заканчивается ряд с фильтрами
  116. ], className = 'row'),
  117.  
  118.  
  119. # здесь начинается ряд с графиками
  120. html.Div([
  121.  
  122. # график (левая сторона ряда)
  123. html.Div([
  124.  
  125. # график истории событий
  126. html.Label('История событий по темам карточек:'),
  127. dcc.Graph(
  128. style = {'height': '50vw'},
  129. id = 'history-absolute-visits'
  130. ),
  131. ], className = 'six columns'),
  132.  
  133. # графики (правая сторона ряда)
  134. html.Div([
  135.  
  136. html.Br(),
  137.  
  138. # график разбивки событий
  139. html.Label('Разбивка событий по темам источников:'),
  140.  
  141. dcc.Graph(
  142. style = {'height': '25vw'},
  143. id = 'pie-visits'
  144. ),
  145.  
  146. # график глубины взаимодействия
  147. html.Label('Глубина взаимодействия:'),
  148.  
  149. dcc.Graph(
  150. style = {'height': '25vw'},
  151. id = 'engagement-graph'
  152. ),
  153.  
  154. ], className = 'six columns'),
  155.  
  156. # здесь заканчивается ряд с графиками
  157.  
  158. ], className = 'row'),
  159.  
  160. # здесь заканчивается дашборд
  161. ])
  162.  
  163. #описываем логику дашборда
  164. @app.callback(
  165. [Output('history-absolute-visits', 'figure'),
  166. Output('pie-visits', 'figure'),
  167. Output('engagement-graph', 'figure'),
  168. ],
  169. [Input('item-topic-dropdown', 'value'),
  170. Input('age_dropdown', 'value'),
  171. Input('dt_selector', 'start_date'),
  172. Input('dt_selector', 'end_date'),
  173. ])
  174. def update_figures(selected_item_topics, selected_ages, start_date, end_date):
  175.  
  176. # применяем фильтрацию
  177. filtered_visits = dash_visits.query('item_topic in @selected_item_topics')
  178. filtered_visits = filtered_visits.query('age_segment in @selected_ages')
  179. filtered_visits = filtered_visits.query('dt >= @start_date and dt <= @end_date')
  180.  
  181. filtered_engagement = dash_engagement.query('item_topic in @selected_item_topics')
  182. filtered_engagement = filtered_engagement.query('age_segment in @selected_ages')
  183. filtered_engagement = filtered_engagement.query('dt >= @start_date and dt <= @end_date')
  184.  
  185.  
  186. # точечная диаграмма
  187. agg_filtered_visits = filtered_visits.groupby(['item_topic', 'dt']).agg({'visits':'sum'}).reset_index()
  188. scatterplot = []
  189. for topic in agg_filtered_visits['item_topic'].unique():
  190. scatterplot += [go.Scatter(x = agg_filtered_visits.query('item_topic == @topic')['dt'],
  191. y = agg_filtered_visits.query('item_topic == @topic')['visits'],
  192. mode = 'lines',
  193. stackgroup = 'one',
  194. name = topic)]
  195.  
  196. # круговая диаграмма
  197. agg_filtered_visits_topic = filtered_visits.groupby(['source_topic']).agg({'visits':'sum'}).reset_index()
  198. pie_chart = [go.Pie(labels = agg_filtered_visits_topic['source_topic'],
  199. values = agg_filtered_visits_topic['visits'])]
  200. # столбчатая диаграмма
  201. agg_engagement = filtered_engagement.groupby('event').agg({'unique_users':'mean'})
  202. agg_engagement.rename(columns={'unique_users':'avg_unique_users'}, inplace=True)
  203. bar_chart = [go.Bar(x = agg_filtered_engagement['event'],
  204. y = agg_filtered_engagement['avg_unique_users'])]
  205. return (
  206.  
  207. {
  208. 'data': scatterplot,
  209. 'layout': go.Layout(xaxis = {'title': 'Дата и время'},
  210. yaxis = {'title': 'Число визитов'})
  211. },
  212. {
  213. 'data': scatterplot,
  214. 'layout': go.Layout()
  215. },
  216. {
  217. 'data': scatterplot,
  218. 'layout': go.Layout(xaxis = {'title': 'Событие'},
  219. yaxis = {'title': 'Число людей'})
  220. }
  221. )
  222.  
  223. if __name__ == '__main__':
  224. app.run_server(debug = True, host = '0.0.0.0', port=3000)
Add Comment
Please, Sign In to add comment