Spaces:
Running
Running
File size: 12,185 Bytes
540fe64 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 |
import streamlit as st
import pandas as pd
from sqlalchemy import create_engine
from PIL import Image
st.set_page_config(page_title="# Анализ данных StackOverflow")
st.markdown('# Анализ данных StackOverflow')
with st.expander("Описание проекта"):
st.write("""
Вы будете работать с базой данных StackOverflow — сервиса вопросов и ответов о программировании.
StackOverflow похож на социальную сеть — пользователи сервиса задают вопросы, отвечают на посты, оставляют комментарии и ставят оценки другим ответам.
Вы будете работать с версией базы, где хранятся данные о постах за 2008 год, но в таблицах вы найдёте информацию и о более поздних оценках, которые эти посты получили.
Описание данных:
- Таблица badges:
Хранит информацию о значках, которые присуждаются за разные достижения. Например, пользователь, правильно ответивший на большое количество вопросов про PostgreSQL, может получить значок postgresql.
- id Идентификатор значка, первичный ключ таблицы
- name Название значка
- user_id Идентификатор пользователя, которому присвоили значок, внешний ключ, отсылающий к таблице users
- creation_date Дата присвоения значка
- Таблица post_types:
Содержит информацию о типе постов. Их может быть два:
- Question — пост с вопросом;
- Answer — пост с ответом.
- id Идентификатор поста, первичный ключ таблицы
- type Тип поста
- Таблица posts:
Содержит информацию о постах.
- id Идентификатор поста, первичный ключ таблицы
- title Заголовок поста
- creation_date Дата создания поста
- favorites_count Число, которое показывает, сколько раз пост добавили в «Закладки»
- last_activity_date Дата последнего действия в посте, например комментария
- last_edit_date Дата последнего изменения поста
- user_id Идентификатор пользователя, который создал пост, внешний ключ к таблице users
- parent_id Если пост написали в ответ на другую публикацию, в это поле попадёт идентификатор поста с вопросом
- post_type_id Идентификатор типа поста, внешний ключ к таблице post_types
- score Количество очков, которое набрал пост
- views_count Количество просмотров
- Таблица users:
Содержит информацию о пользователях.
- id Идентификатор пользователя, первичный ключ таблицы
- creation_date Дата регистрации пользователя
- display_name Имя пользователя
- last_access_date Дата последнего входа
- location Местоположение
- reputation Очки репутации, которые получают за хорошие вопросы и полезные ответы
- views Число просмотров профиля пользователя
- Таблица vote_types:
Содержит информацию о типах голосов. Голос — это метка, которую пользователи ставят посту. Типов бывает несколько:
- UpMod — такую отметку получают посты с вопросами или ответами, которые пользователи посчитали уместными и полезными.
- DownMod — такую отметку получают посты, которые показались пользователям наименее полезными.
- Close — такую метку ставят опытные пользователи сервиса, если заданный вопрос нужно доработать или он вообще не подходит для платформы.
- Offensive — такую метку могут поставить, если пользователь ответил на вопрос в грубой и оскорбительной манере, например, указав на неопытность автора поста.
- Spam — такую метку ставят в случае, если пост пользователя выглядит откровенной рекламой.
- id Идентификатор типа голоса, первичный ключ
- name Название метки
- Таблица votes:
Содержит информацию о голосах за посты.
- id Идентификатор голоса, первичный ключ
- post_id Идентификатор поста, внешний ключ к таблице posts
- user_id Идентификатор пользователя, который поставил посту голос, внешний ключ к таблице users
- bounty_amount Сумма вознаграждения, которое назначают, чтобы привлечь внимание к посту
- vote_type_id Идентификатор типа голоса, внешний ключ к таблице vote_types
- creation_date Дата назначения голоса
""")
db_config = {
'user': 'praktikum_student', # имя пользователя
'pwd': 'Sdf4$2;d-d30pp', # пароль
'host': 'rc1b-wcoijxj3yxfsf3fs.mdb.yandexcloud.net',
'port': 6432, # порт подключения
'db': 'data-analyst-advanced-sql' # название базы данных
}
connection_string = 'postgresql://{}:{}@{}:{}/{}'.format(
db_config['user'],
db_config['pwd'],
db_config['host'],
db_config['port'],
db_config['db'],
)
engine = create_engine(connection_string)
def query_db(query):
return pd.read_sql_query(query, con=engine)
query_1 = '''SELECT date_trunc('month', creation_date) as month_date, sum(views_count) as total_views
FROM stackoverflow.posts
WHERE extract( YEAR from creation_date) = '2008'
GROUP BY month_date
ORDER BY total_views DESC
'''
query_2 = '''SELECT u.display_name, count(DISTINCT p.user_id)
FROM stackoverflow.users as u
JOIN stackoverflow.posts as p ON p.user_id = u.id
JOIN stackoverflow.post_types as pt ON pt.id = p.post_type_id
WHERE pt.type = 'Answer' AND
p.creation_date::date BETWEEN u.creation_date AND (u.creation_date::date + INTERVAL '1 month')
GROUP BY u.display_name
HAVING count(p.user_id)>100
ORDER BY u.display_name
'''
query_3 = '''WITH dt as (SELECT u.id
FROM stackoverflow.posts as p
JOIN stackoverflow.users as u ON p.user_id = u.id
WHERE DATE_TRUNC('month', u.creation_date) = '2008-09-01' AND
DATE_TRUNC('month', p.creation_date) = '2008-12-01')
SELECT date_trunc('month', p.creation_date)::date as month, count(p.id)
FROM stackoverflow.posts as p
WHERE p.user_id in (SELECT * FROM dt) AND
EXTRACT(YEAR FROM p.creation_date) = '2008'
GROUP BY month
ORDER BY month DESC
'''
query_4 = '''SELECT user_id, AVG(avg_daily)
FROM (SELECT DISTINCT user_id, date_trunc('day', creation_date)::date as t,
count(id) OVER (PARTITION BY user_id, date_trunc('day', creation_date)::date) as avg_daily,
count(id) OVER (PARTITION BY user_id, date_trunc('month', creation_date)::date) as cnt
FROM stackoverflow.posts
WHERE date_trunc('month', creation_date)::date = '2008-08-01') as dt
WHERE cnt>120
GROUP BY user_id
ORDER BY AVG(avg_daily)
'''
examples = {'Выводит общую сумму просмотров постов за каждый месяц 2008 года':query_1,
'Выводит имена самых активных пользователей, которые в первый месяц после регистрации (включая день регистрации) дали больше 100 ответов':query_2,
'Выводит количество постов за 2008 год по месяцам. Отбирает посты от пользователей, которые зарегистрировались в сентябре 2008 года и сделали хотя бы один пост в декабре того же года.':query_3,
'Найдет среднее количество постов пользователей в день за август 2008 года. Отберет данные о пользователях, которые опубликовали больше 120 постов за август. Дни без публикаций не учитывает.':query_4,
}
with st.expander("Схема быза данных"):
image = Image.open('image/Frame.png')
st.image(image)
with st.expander("Примеры SQL запросов"):
query = st.selectbox('Выберете один из запросов:', ('Выводит общую сумму просмотров постов за каждый месяц 2008 года',
'Выводит имена самых активных пользователей, которые в первый месяц после регистрации (включая день регистрации) дали больше 100 ответов',
'Выводит количество постов за 2008 год по месяцам. Отбирает посты от пользователей, которые зарегистрировались в сентябре 2008 года и сделали хотя бы один пост в декабре того же года.',
'Найдет среднее количество постов пользователей в день за август 2008 года. Отберет данные о пользователях, которые опубликовали больше 120 постов за август. Дни без публикаций не учитывает.',
))
st.code(examples[query], language="sql", line_numbers=False)
if st.button("Запуск запроса"):
st.markdown('## Результат запроса:')
st.write(query_db(examples[query]))
def submit():
st.session_state.title = st.session_state.widget
st.session_state.widget = ""
st.text_input("Введите ваш SQL запрос", key="widget", on_change=submit)
if 'title' not in st.session_state:
st.session_state.title = ""
title = st.session_state.title
# st.write(title)
# title = st.text_input('Введите ваш SQL запрос')
if title:
st.markdown('## Ваш запрос:')
st.code(title, language="sql", line_numbers=False)
st.markdown('## Результат запроса:')
try:
st.write(query_db(title))
except:
'Запрос неверен, убедитесь в правильности запроса'
|