При получении вами критического (красного) замечания по проекту, проведу правки.
Решение сдесь: Добавь в корзину - Перейди в корзину - Укажи Email - Оплатить по СБП - СБП (приложение вашего банка) - Получи решение на Email
Не можешь оплатить, тогда через "Помощь" запроси другую систему оплаты (Webmoney, Alipay, Telegram (USDT, TON)).
Внимательно: Ниже представлено правильное решение, но его посмотрело уже больше 5000 человек. Думаю, что им можно пользоваться только для руководства при написании самостоятельного проекта, но сдавать без правок уже нельзя, есть вероятность получить замечание от опытных ревьюеров: "Это плагиат! Переделайте решение" и потом думать как всё исправить.
Поэтому принято решение переделать проект заново и ограничить доступ к нему введя символическую оплату. Также поступлю и с последующими проектами. За готовым решением переходи по ссылке выше.
Вернуться в раздел: Сборный Проект — 1
Вернуться в оглавление: Я.Практикум
Сборный проект №1
Цель исследования — для руководства интернет магазина "Стримчик" (интернет магазин продающий компьютерные игры по всему миру) требуется отработать принцип работы с данными и выявить определяющие успешность игры закономерности, что позволит сделать ставку на потенциально популярный продукт и спланировать рекламные кампании.
Описание данных
Name— название игрыPlatform— платформаYear_of_Release— год выпускаGenre— жанр игрыNA_sales— продажи в Северной Америке (миллионы проданных копий)EU_sales— продажи в Европе (миллионы проданных копий)JP_sales— продажи в Японии (миллионы проданных копий)Other_sales— продажи в других странах (миллионы проданных копий)Critic_Score— оценка критиков (максимум 100)User_Score— оценка пользователей (максимум 10)Rating— рейтинг от организации ESRB (англ. Entertainment Software Rating Board). Эта ассоциация определяет рейтинг компьютерных игр и присваивает им подходящую возрастную категорию.
Исследование проедем в соответствии с планом:
- Изучим общую информацию
- Предобработка данных
- Проведем исследовательский анализ данных
- Составим портрет пользователя каждого региона
- Проверим гипотезы
- Напишем вывод
1.1 Импорт библиотек
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
from scipy import stats as st
1.2 Чтение данных
df = pd.read_csv('/datasets/games.csv')
df.head()
1.3 Получение общей информации о данных
df.info()
Вывод по ознакомлению с данными:
- Всего в таблице 16715 строк и 11 колонок в шести колонках имеются пропуски в данных
- Названия колонок имеют нарушение стилей
- Ряд колонок имеет неверный тип
- Данных достаточно для проведения исследования
df.columns
df.columns = df.columns.str.lower()
df.columns
2.2 Удаление полных дубликатов
df = df.drop_duplicates()
print(df[df.duplicated(['name', 'platform', 'year_of_release'])].count())
print(df[df.duplicated(['name', 'platform', 'year_of_release'])])
df = df.drop_duplicates(['name', 'platform', 'year_of_release'])
print(df[df.duplicated(['name', 'platform', 'year_of_release'])].count())
Во всех данных провели поиск неявных дубликатов одновременно по столбцам name, platform, year_of_release. Таких дубликатов оказалось всего два. Обобразили количество повторов по столбцам. Вывели эти строки и удалили с последующей проверкой.
nameprint('В столбце `name` нет значений в ', (df['name'].isnull().sum() / len(df['name'])*100).round(3), '% данных. \nПри значении меньше 1 % примем решение удалить строки с пропусками в столбце `name` \nТогда всего пропусков останется \n')
df = df.dropna(subset=['name'])
df.isna().sum()
Обработка year_of_release
print('В столбце `year_of_release` нет значений в ', (df['year_of_release'].isnull().sum() / len(df['name'])*100).round(3), '% данных')
df = df.dropna(subset=['year_of_release'])
df.isna().sum()
Обработка critic_score
df['critic_score'].isna().sum() / len(df['name'])*100
Количество пропусков больше 51 %. Заменить на медиану и среднее нецелесообразно. Пометим отрицательным значением "-1"
df['critic_score'] = df['critic_score'].fillna(-1)
Обработка user_score
df['user_score'].isna().sum() / len(df['name'])*100
Количество пропусков больше 40 %. Заменить на медиану и среднее нецелесообразно. Пометим отрицательным значением "-1"
df['user_score'] = df['user_score'].fillna(-1)
df['user_score'].value_counts()
df[df['user_score']=='tbd']['user_score'].count() / len(df['name'])*100
В столбце имеется оценка tbd не описанная в полученных данных, при этом ее значение больше 14%. Игнорировать это нельзя обозначим как "-1"
df.loc[df['user_score'] == 'tbd', 'user_score'] = -1
df['user_score'].value_counts()
Обработка rating
df['rating'].isna().sum() / len(df['name'])*100
Количество пропусков больше 40 %. Заменить на медиану и среднее нецелесообразно. Пометим что возрастная категория неизвестна "unknown"
df['rating'] = df['rating'].fillna('unknown')
df.isna().sum()
2.4 Преобразование типов столбцов
df.info()
df['year_of_release'] = (df['year_of_release']).astype('int')
df['critic_score'] = (df['critic_score']).astype('int')
df['user_score'] = (df['user_score']).astype('float')
df.info()
2.5 Посчитаем суммарные продажи во всех регионах и запишем их в отдельный столбец.
df['total_sales'] = data.loc[:,['na_sales','eu_sales', 'jp_sales', 'other_sales']].sum(axis=1)
df.head()
Вывод по предобработке данных:
- Явные дубликаты не обнаружены
- Удалены строки с неявными дубликатами поиск одновременно по 'name', 'platform', 'year_of_release'
- По столбцу
nameудалены 2 строки с пропусками - По столбцу
year_of_releaseпринято решение удалить строки с пропусками - В столбце
critic_scoreколичество пропусков больше 51% они обозначены как-1 - В столбце
user_scoreколичество пропусков больше 40% они обозначены как-1, неописанное значениеtbdобозначено как-2 - В столбце
ratingпропуски обозначены какunknown - Столбцы
year_of_release,critic_scoreприведены кintтипу,user_scoreкfloatв соответствии с данными содержащимися в них. - Пропуски могли появиться из за сбора данных из различных источников, которые не согласованы между собой.
- Посчитали суммарные продажи во всех регионах записали в
total_sales
3. Проведем исследовательский анализ данных¶
(
df
#.query('year_of_release > -1') #Строки с пропусками удалены
.pivot_table(index='year_of_release', values='name', aggfunc='count')
.plot(kind='bar' , grid=True, figsize=(10, 5))
)
plt.title('Количество продаж по годам')
plt.xlabel('Год')
plt.ylabel('Количество продаж')
plt.show()
df[df['year_of_release'] > -1]['year_of_release'].describe()
Резюме по выпуску игр по годам
- В таблице представлены игры с выпуском с 1980 по 2016 год.
- Присутствуют игры у которых не указан год выпуска в количестве 269
- Рост числа выпуска игр приходится на 1995 год, с максимумом примерно в 2007 году после чего прослеживается спад.
- С 2012 года объем выпуска игр стабилизировался и год от года отличается несильно.
- В целях исследования логично выбрать период в 5 - 10 лет (старые игры забываются, новые сильнее влияют на рынок).
(
df.pivot_table(index='platform', values='total_sales', aggfunc='sum')
.sort_values(by='total_sales', ascending=False)
.plot(kind='bar' , grid=True, figsize=(10, 5))
)
plt.title('Количество суммарных продаж в зависимости от платформы')
plt.xlabel('Платформа')
plt.ylabel('Суммарные продажи')
plt.show()
Наибоше суммарных продаж зафиксировано у 6 платформ
top_sales = df.pivot_table(index='platform', values='total_sales', aggfunc='sum').sort_values(by='total_sales', ascending=False).reset_index().head(6)['platform'].tolist()
top_sales
for name in top_sales:
(
df.query('platform == @name and year_of_release > -1')
.pivot_table(index = 'year_of_release', values = 'total_sales', aggfunc = 'sum')
.sort_values('year_of_release', ascending = False)['total_sales']
.plot(figsize = (10, 5), label=name)
)
plt.title('Жизненный цикл шести платформ с максимальными продажами')
plt.xlabel('Год выпуска')
plt.ylabel('Суммарные продажи')
plt.legend()
Проанализируем артефакт на графике по консоли DS
print(df.query('platform == "DS" and year_of_release < 1990'))
В данных только одна строка и это явная ошибка возникшая при заполнении данных в столбце nameю Принимаем решение удалить эту строку по её индексу и перестроить график жизненного цикла консолей.
df = df.drop(index = 15957)
for name in top_sales:
(
df.query('platform == @name')
.pivot_table(index = 'year_of_release', values = 'total_sales', aggfunc = 'sum')
.sort_values('year_of_release', ascending = False)['total_sales']
.plot(figsize = (10, 5), label=name)
)
plt.title('Жизненный цикл шести платформ с максимальными продажами')
plt.xlabel('Год выпуска')
plt.ylabel('Суммарные продажи')
plt.legend()
Расчитаем время жизненного цикла по всем данным
time_life = df.pivot_table(index='platform', values='year_of_release', aggfunc=['min', 'max']).reset_index()
# в срок жизни платформы, должны входить границы диапазона, поэтому +1
time_life['life'] = time_life['max'] - time_life['min'] + 1
print('Медианное значение жизненного цикла по всей выборке', time_life['life'].median(), 'лет')
В исследовании нас больше интерисует, когда продажи по платформам растут или когда она находится на пике а это первая половина жизненного цикла платформ, с округлением в большую сторону.
t = np.ceil(time_life['life'].median()/2)
print('Определим актуальный период за последние', t, 'года')
Вывод по исследованию платформ
Из графиков видно, что от срока появления платформы до их исчезновения как правило проходит 10 лет, следовательно для нас интересны платформы релдиз которых состоялся 3-5 годами ранее и которые активно растут в продажах. Определим, что актуальный период составляет 4 последних года.
actual_platforms = (df
.query('year_of_release >= 2016-@t')
.pivot_table(index='platform', values='total_sales', aggfunc='sum')
.sort_values(by='total_sales', ascending=False)
.reset_index().head(10)['platform'].tolist()
)
actual_platforms
actual_df = df.query('year_of_release >= 2016-@t').copy().reset_index(drop= True)
actual_df.head()
for name in actual_platforms:
(
actual_df.query('platform == @name')
.pivot_table(index = 'year_of_release', values = 'total_sales', aggfunc = 'sum')
.sort_values('year_of_release', ascending = False)['total_sales']
.plot(kind='line', figsize = (10, 5), label=name)
)
plt.title('Жизненный цикл всех платформ за актуальный период')
plt.xticks(np.arange(2012, 2018, step=1))
plt.xlabel('Год')
plt.ylabel('Суммарные продажи')
plt.legend()
Из графика видно, что на 2016 год нет явно возрастающих продаж по консолям, продажи падают на всех консолях. Более или менее перспективными являются консоли PS4 и XOne но у них также прослеживаются уменьшения продаж.
plt.figure(figsize=(12,6))
sns.boxplot(data=actual_df, x='platform', y='total_sales')
plt.title('Продажи по перспективным платформам с выбросами', fontsize=15)
plt.xlabel('Платформа', fontsize=12)
plt.ylabel('Продажи по платформам',fontsize=12)
actual_df['total_sales'].describe()
plt.figure(figsize=(12,6))
ax = sns.boxplot(data=actual_df, x='platform', y='total_sales')
ax.set(ylim=(0,2))
plt.title('Продажи по перспективным платформам с крупными `Boxplot`', fontsize=15)
plt.xlabel('Платформа', fontsize=12)
plt.ylabel('Продажи по платформам',fontsize=12)
Вывод по построению диаграммы Boxplot
Описательная статистика данных за актуальный период указывает, что:
- Медианное значение по всей выборке составляет 0,12 но у большинства консолей данный показатель не совпадает с основным.
- По первой и третьей квартили также наблюдается большой разброс.
- По всем консолям присутствуют выбросы по продажам.
Отберем 5 платформ с максимальными продажами
actual_platforms_5 = (actual_df
.pivot_table(index='platform', values='total_sales', aggfunc='sum')
.sort_values(by='total_sales', ascending=False)
.reset_index().head(5)['platform'].tolist()
)
actual_platforms_5
Построим диаграмму распределения и вычислим корреляцию между оценкой пользователей и продажами в разрезе отдельных платформ
for name in actual_platforms_5:
(
actual_df
.query('platform == @name and user_score > -1')
.plot(x='user_score',
y='total_sales',
kind='scatter',
figsize=(10, 5),
color='blue')
)
plt.title(f'Диаграмма распределения между оценками пользователей и продажами по платформе {name}')
plt.xlabel('Оценка пользователей')
plt.ylabel('Продажи')
plt.legend([name])
print(f'Корреляция между оценками пользователей и продажами по платформе {name} =', actual_df.query('platform == @name and user_score > -1')['user_score'].corr(actual_df.query('platform == @name and user_score > -1')['total_sales']))
plt.show()
Построим диаграмму распределения и вычислим корреляцию между оценкой критиков и продажами в разрезе отдельных платформ
for name in actual_platforms_5:
(
actual_df
.query('platform == @name and critic_score > -1')
.plot(x='critic_score',
y='total_sales',
kind='scatter',
figsize=(10, 5),
color='green')
)
plt.title(f'Диаграмма распределения между оценками критиков и продажами по платформе {name}')
plt.xlabel('Оценка критиков')
plt.ylabel('Продажи')
plt.legend([name])
print(f'Корреляция между оценками критиков и продажами по платформе {name} =', actual_df.query('platform == @name and critic_score > -1')['critic_score'].corr(actual_df.query('platform == @name and critic_score > -1')['total_sales']))
plt.show()
Сделаем аналогичные расчеты для всего набора данных.
print('Общая корреляция между оценками пользователей и продажами = ', actual_df.query('user_score > -1')['user_score'].corr(actual_df['total_sales']))
print('Общая корреляция между оценками критиков и продажами = ', actual_df.query('critic_score > -1')['critic_score'].corr(actual_df['total_sales']))
(
actual_df.query('user_score > -1')
.plot(x='user_score',
y='total_sales',
kind='scatter',
figsize=(10, 5),
color='blue')
)
plt.title('Диаграмма распределения между оценками пользователей и продажами', fontsize=15)
plt.xlabel('Оценка пользователей', fontsize=12)
plt.ylabel('Продажи',fontsize=12)
plt.show()
(
actual_df.query('critic_score > -1')
.plot(x='critic_score',
y='total_sales',
kind='scatter',
figsize=(10, 5),
color='green')
)
plt.title('Диаграмма распределения между оценками критиков и продажами', fontsize=15)
plt.xlabel('Оценка критиков', fontsize=12)
plt.ylabel('Продажи',fontsize=12)
plt.show()
- Диаграммы распределения явно показывают на слабую связь между оценкой пользователей и продажами по всей совокупности данных (приближается к 0,004).
- Диаграммы распределения явно показывают на умеренную связь между оценкой критиков и продажами в разрезе отдельных платформ, соответствующий коэффициент корреляции подтверждает это (приближается к 0,31).
Диаграммы зависимости оценок на показатели продаж и коэффициенты корреляции по отдельным платформам указывают, что:
- между оценками пользователей и продажами слабая связь и нелинейная
- между оценками критиков и продажами связь умеренная и скорее всего нелинейная
По отношению к общим показателям значения даже больше, что указывает на то что, по всем платформам:
- между оценками пользователей и продажами слабая связь и нелинейная
- между оценками критиков и продажами связь умеренная и скорее всего нелинейная
(actual_df
.pivot_table(index='genre', values='total_sales', aggfunc='sum')
.sort_values('total_sales', ascending=False)
.plot(kind='bar', y='total_sales', figsize=(10, 5), legend=False,title = 'Прибыльность жанров в актуальном периоде')
.set(xlabel='Жанр игры', ylabel='Всего продаж по жанру'))
plt.show()
plt.figure(figsize=(12,6))
ax = sns.boxplot(data=actual_df, x='genre', y='total_sales')
plt.title('Продажи по перспективным жанрам', fontsize=15)
plt.xlabel('Жанр', fontsize=12)
plt.ylabel('Продажи по жанрам',fontsize=12)
plt.figure(figsize=(12,6))
ax = sns.boxplot(data=actual_df, x='genre', y='total_sales')
ax.set(ylim=(0,1.5))
plt.title('Продажи по перспективным жанрам', fontsize=15)
plt.xlabel('Жанр', fontsize=12)
plt.ylabel('Продажи по жанрам',fontsize=12)
Вернуться в раздел: Сборный Проект — 1
Вернуться в оглавление: Я.Практикум