Advertisement
12311k

Untitled

Feb 21st, 2021
69
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.76 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. #задаём данные для отрисовки
  16. from sqlalchemy import create_engine
  17.  
  18. # пример подключения к базе данных для Postresql
  19. #db_config = {'user': 'my_user',
  20. # 'pwd': 'my_user_password',
  21. # 'host': 'localhost',
  22. # 'port': 5432,
  23. # 'db': 'games'}
  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. # пример подключения к базе данных для Sqlite
  30. engine = create_engine('sqlite:////db/games.db', echo = False)
  31.  
  32. # получаем сырые данные
  33. query = '''
  34. SELECT * FROM data_raw
  35. '''
  36. games_raw = pd.io.sql.read_sql(query, con = engine)
  37.  
  38. # преобразовываем типы
  39. games_raw['year_of_release'] = pd.to_datetime(games_raw['year_of_release'])
  40. columns = ['na_players', 'eu_players', 'jp_players', 'other_players']
  41. for column in columns: games_raw[column] = pd.to_numeric(games_raw[column], errors = 'coerce')
  42.  
  43. # формируем данные для отчёта
  44. games_grouped = (games_raw.groupby(['year_of_release', 'genre'])
  45. .agg({'name': 'nunique'})
  46. .reset_index()
  47. .rename(columns = {'name': 'games_launched'})
  48. )
  49.  
  50. # задаём лейаут
  51. external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
  52. app = dash.Dash(__name__, external_stylesheets=external_stylesheets,compress=False)
  53. app.layout = html.Div(children=[
  54.  
  55. # формируем заголовок тегом HTML
  56. html.H1(children = 'Выпуск игр по годам'),
  57.  
  58. # выбор временного периода
  59. html.Label('Временной период:'),
  60. dcc.DatePickerRange(
  61. start_date = games_grouped['year_of_release'].dt.date.min(),
  62. end_date = datetime(2016,1,1).strftime('%Y-%m-%d'),
  63. display_format = 'YYYY-MM-DD',
  64. id = 'dt_selector',
  65. ),
  66.  
  67. # выбор режима отображения абсолютные/относительные значения
  68. html.Label('Режим отображения:'),
  69. dcc.RadioItems(
  70. options = [
  71. {'label': 'Абсолютные значения', 'value': 'absolute_values'},
  72. {'label': '% от общего выпуска', 'value': 'relative_values'},
  73. ],
  74. value = 'absolute_values',
  75. id = 'mode_selector'
  76. ),
  77.  
  78. # выбор жанра
  79. html.Label('Жанры:'),
  80. dcc.Dropdown(
  81. options = [{'label': x, 'value': x} for x in games_grouped['genre'].unique()],
  82. value = games_grouped['genre'].unique().tolist(),
  83. multi = True,
  84. id = 'genre_selector'
  85. ),
  86.  
  87. # график выпуска игр по годам
  88. dcc.Graph(
  89. id = 'sales_by_year'
  90. ),
  91.  
  92. ])
  93.  
  94. # описываем логику дашборда
  95. @app.callback(
  96. [Output('sales_by_year', 'figure'),
  97. ],
  98. [Input('dt_selector', 'start_date'),
  99. Input('dt_selector', 'end_date'),
  100. Input('mode_selector', 'value'),
  101. Input('genre_selector', 'value'),
  102. ])
  103. def update_figures(start_date, end_date, mode, selected_genres):
  104.  
  105. # приводим входные параметры к нужным типам
  106. start_date = datetime.strptime(start_date, '%Y-%m-%d')
  107. end_date = datetime.strptime(end_date, '%Y-%m-%d')
  108.  
  109. # применяем фильтрацию
  110. filtered_data = games_grouped.query('year_of_release >= @start_date and year_of_release <= @end_date')
  111. filtered_data = filtered_data.query('genre in @selected_genres')
  112.  
  113. # трансформируем в соотв. с выбранным режимом отображения
  114. if mode == 'relative_values':
  115. total_by_year = (filtered_data.groupby('year_of_release')
  116. .agg({'games_launched': 'sum'})
  117. .rename(columns = {'games_launched': 'total'})
  118. )
  119. filtered_data = (filtered_data.set_index('year_of_release')
  120. .join(total_by_year)
  121. .reset_index())
  122. filtered_data['games_launched'] = filtered_data['games_launched'] / filtered_data['total']
  123.  
  124. # формируем графики для отрисовки с учётом фильтров
  125. data = []
  126. for genre in filtered_data['genre'].unique():
  127. data += [go.Scatter(x = filtered_data.query('genre == @genre')['year_of_release'],
  128. y = filtered_data.query('genre == @genre')['games_launched'],
  129. mode = 'lines',
  130. stackgroup = 'one',
  131. name = genre)]
  132.  
  133. # формируем результат для отображения
  134. return (
  135. {
  136. 'data': data,
  137. 'layout': go.Layout(xaxis = {'title': 'Дата и время'},
  138. yaxis = {'title': 'Выпущенные игры'})
  139. },
  140. )
  141.  
  142. if __name__ == '__main__':
  143. app.run_server(host='0.0.0.0', port=3000)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement