Описание проекта
Из открытых источников доступны исторические данные о продажах игр, оценки пользователей и экспертов, жанры и платформы (например, Xbox или PlayStation). Вам нужно выявить определяющие успешность игры закономерности. Это позволит интернет-магазину «Стримчик» сделать ставку на потенциально популярный продукт и спланировать рекламные кампании.
Перед вами данные до 2016 года. Представим, что сейчас декабрь 2016 г., и вы планируете кампанию на 2017-й. Нужно отработать принцип работы с данными. Неважно, прогнозируете ли вы продажи на 2017 год по данным 2016-го или же 2027-й — по данным 2026 года.
Описание данных
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). Эта ассоциация определяет рейтинг компьютерных игр и присваивает им подходящую возрастную категорию.
Данные за 2016 год могут быть неполными.
Оглавление
- 1 Шаг 1. Открытие файла с данными и изучение общей информации
- 2 Шаг 2. Подготовка данных
- 3 Шаг 3. Исследовательский анализ данных
- 3.1 Количество игр, выпускаемых в разные годы
- 3.2 Изменения продаж по платформам.
- 3.3 Выбор данных за актуальный период
- 3.4 Какие платформы лидируют по продажам, растут или падают?
- 3.5 График «ящик с усами» по глобальным продажам игр в разбивке по платформам
- 3.6 Влияние отзывов критиков и пользователей на продажи отдельно взятых платформ всех вместе
- 3.7 Общее распределение игр по жанрам
- 3.8 Итоги исследовательского анализа данных
- 4 Шаг 4. Портрет пользователя каждого региона
- 5 Шаг 5. Проверка гипотез
- 6 Шаг 6. Общий вывод
Шаг 1. Открытие файла с данными и изучение общей информации¶
# Датафреймы
import pandas as pd
# Математика для массивов
import numpy as np
# Факториалы
from math import factorial
# Статистика
from scipy import stats as st
# Графика
import matplotlib
%matplotlib inline
from matplotlib import pyplot as plt
from matplotlib import rcParams, rcParamsDefault
import seaborn as sns
# Отображение всех столбцов таблицы
pd.set_option('display.max_columns', None)
# Обязательно для нормального отображения графиков plt
rcParams['figure.figsize'] = 10, 6
%config InlineBackend.figure_format = 'svg'
# Дополнительно и не обязательно для декорирования графиков
factor = .8
default_dpi = rcParamsDefault['figure.dpi']
rcParams['figure.dpi'] = default_dpi * factor
try:
games = pd.read_csv('/datasets/games.csv')
except:
games = pd.read_csv('datasets/games.csv')
games.head()
Name | Platform | Year_of_Release | Genre | NA_sales | EU_sales | JP_sales | Other_sales | Critic_Score | User_Score | Rating | |
---|---|---|---|---|---|---|---|---|---|---|---|
0 | Wii Sports | Wii | 2006.0 | Sports | 41.36 | 28.96 | 3.77 | 8.45 | 76.0 | 8 | E |
1 | Super Mario Bros. | NES | 1985.0 | Platform | 29.08 | 3.58 | 6.81 | 0.77 | NaN | NaN | NaN |
2 | Mario Kart Wii | Wii | 2008.0 | Racing | 15.68 | 12.76 | 3.79 | 3.29 | 82.0 | 8.3 | E |
3 | Wii Sports Resort | Wii | 2009.0 | Sports | 15.61 | 10.93 | 3.28 | 2.95 | 80.0 | 8 | E |
4 | Pokemon Red/Pokemon Blue | GB | 1996.0 | Role-Playing | 11.27 | 8.89 | 10.22 | 1.00 | NaN | NaN | NaN |
Названия столбцов выполнены не в «змеином стиле». В данных наблюдаются пропуски.
games.info()
<class 'pandas.core.frame.DataFrame'> RangeIndex: 16715 entries, 0 to 16714 Data columns (total 11 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 Name 16713 non-null object 1 Platform 16715 non-null object 2 Year_of_Release 16446 non-null float64 3 Genre 16713 non-null object 4 NA_sales 16715 non-null float64 5 EU_sales 16715 non-null float64 6 JP_sales 16715 non-null float64 7 Other_sales 16715 non-null float64 8 Critic_Score 8137 non-null float64 9 User_Score 10014 non-null object 10 Rating 9949 non-null object dtypes: float64(6), object(5) memory usage: 1.4+ MB
В датафрейме всего 11 столбцов и 16715 строк. 7 столбцов содержат пропуски. Вес датафрейма 1.4 Мб. Возможно, использованы неоптимальные типы данных в столбцах.
games.describe()
Year_of_Release | NA_sales | EU_sales | JP_sales | Other_sales | Critic_Score | |
---|---|---|---|---|---|---|
count | 16446.000000 | 16715.000000 | 16715.000000 | 16715.000000 | 16715.000000 | 8137.000000 |
mean | 2006.484616 | 0.263377 | 0.145060 | 0.077617 | 0.047342 | 68.967679 |
std | 5.877050 | 0.813604 | 0.503339 | 0.308853 | 0.186731 | 13.938165 |
min | 1980.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 13.000000 |
25% | 2003.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 60.000000 |
50% | 2007.000000 | 0.080000 | 0.020000 | 0.000000 | 0.010000 | 71.000000 |
75% | 2010.000000 | 0.240000 | 0.110000 | 0.040000 | 0.030000 | 79.000000 |
max | 2016.000000 | 41.360000 | 28.960000 | 10.220000 | 10.570000 | 98.000000 |
Можно изменить типы данных столбцов:
Year_of_Release
наuint16
, т.к. года являются четырёхзначными натуральными числами;NA_sales
,EU_sales
,JP_sales
,Other_sales
,Critic_Score
иUser_Score
наfloat16
, т.к. в этих столбцах использованы рациональные числа небольшой размерности.
Анализ отдельных столбцов датафрейма¶
Одновременные дубликаты в Name
, Platform
и Year_of_Release
¶
# Поиск дубликатов по ключевым столбцам
# с названием игры, платформы и годом выпуска
games.loc[games.duplicated(['Name', 'Platform', 'Year_of_Release'])]
Name | Platform | Year_of_Release | Genre | NA_sales | EU_sales | JP_sales | Other_sales | Critic_Score | User_Score | Rating | |
---|---|---|---|---|---|---|---|---|---|---|---|
14244 | NaN | GEN | 1993.0 | NaN | 0.0 | 0.00 | 0.03 | 0.0 | NaN | NaN | NaN |
16230 | Madden NFL 13 | PS3 | 2012.0 | Sports | 0.0 | 0.01 | 0.00 | 0.0 | 83.0 | 5.5 | E |
Найдено два дубликата по столбцам с названием игры, платформы и годом выпуска. Требуется проверка повторяющихся строк.
games.loc[
((games['Name'].isna()) &
(games['Platform'] == 'GEN') &
(games['Year_of_Release'] == 1993)) |
((games['Name'] == 'Madden NFL 13') &
(games['Platform'] == 'PS3') &
(games['Year_of_Release'] == 2012))
]
Name | Platform | Year_of_Release | Genre | NA_sales | EU_sales | JP_sales | Other_sales | Critic_Score | User_Score | Rating | |
---|---|---|---|---|---|---|---|---|---|---|---|
604 | Madden NFL 13 | PS3 | 2012.0 | Sports | 2.11 | 0.22 | 0.00 | 0.23 | 83.0 | 5.5 | E |
659 | NaN | GEN | 1993.0 | NaN | 1.78 | 0.53 | 0.00 | 0.08 | NaN | NaN | NaN |
14244 | NaN | GEN | 1993.0 | NaN | 0.00 | 0.00 | 0.03 | 0.00 | NaN | NaN | NaN |
16230 | Madden NFL 13 | PS3 | 2012.0 | Sports | 0.00 | 0.01 | 0.00 | 0.00 | 83.0 | 5.5 | E |
Строки с пропуском в названии игры требуется удалить, т.к. во многих аттрибутах этих объектов пропуски. Строки с игрой Madden NFL 13
, выпущенной в 2012 году на платформе PS3
желательно объеденить.
Пропуски в ‘Rating’ с рейтингом ESRB¶
Для анализа столбца с рейтингом ESRB (Entertainment Software Rating Board) требуется выявиться существующие позиции этого рейтинга. (https://www.ph4.ru/pal_picto.php?p=ratings-esrb&titl=ESRB, 2023):
- EC — Early childhood (Для детей младшего возраста). Игра подходит для детей от 3 лет и старше и не содержит материалов, которые родители могли бы счесть неподходящими. Продукты, получившие данный рейтинг, изначально разрабатываются для детей и обычно представляют собой развивающие игры. Некоторые усложнённые развивающие игры могут иметь рейтинг Everyone».
- E — Everyone (Для всех). Содержание вполне подходит для возрастной категории от 6 лет и старше
- E10+ — Everyone 10 and older (Для всех старше 10 лет). Возрастная категория — от 10 лет. Проекты с данным рейтингом могут содержать немного больше мультипликационного или мягкого насилия, или несколько откровенные сцены или минимальное количество крови. Рейтинг был принят ESRB 2 марта 2005 года. Первой игрой, которая получила данный рейтинг, стала Donkey Kong: Jungle Beat.
- T — Teen (Подросткам). Игра подходит для лиц от 13 лет и старше. Проекты из данной категории могут содержать насилие, непристойные сцены, грубый юмор, в меру откровенное сексуальное содержимое, кровь или нечастое использование ненормативной лексики.
- M — Mature (От 17 лет). Материалы игры не подходят для подростков младше 17 лет. Проекты с данным рейтингом могут содержать достаточно жестокое насилие, большое количество крови с расчленением, непристойные сексуальные сцены или грубую ненормативную лексику, нежелательную для младшей аудитории. Некоторые торговые сети не продают игры с таким рейтингом несовершеннолетним без согласия родителей.
- AO — Adults Only 18+ (Только для взрослых). Содержание игры только для взрослых. Продукты из данной категории могут содержать длительные сцены жестокого насилия и/или очень откровенное сексуальное содержимое, а также сцены с обнажением. В 2006-м году данный рейтинг получили 22 продукта, большинство из которых предназначены для персональных компьютеров под управлением Windows и Apple Macintosh. Рейтинг Только для взрослых» является предметом
- RP — Rating Pending (Рейтинг ожидается). Продукт был отправлен в ESRB и ожидает присвоения рейтинга. Данный логотип используется только на рекламных презентациях и в демо-версиях игр до официального релиза.
- K-A — Kids to Adults (Для детей и взрослых). Содержание игры вполне подходит для возрастной категории от 6 лет и старше. Такие игры подходят для всех возрастов. Они могут содержать минимальное насилие или немного грубый разговорный язык. Этот рейтинг был заменён на Everyone.
Рейтинг ESRB (Википедия, 2023):
- «EC» («Early childhood») — «Для детей младшего возраста»: Игра подходит для детей от 3 лет и не содержит материалов, которые родители могли бы счесть неподходящими. Продукты, получившие данный рейтинг, изначально разрабатываются для детей и обычно представляют собой развивающие игры.
- «E» («Everyone») — «Для всех»: Содержание вполне подходит для всех возрастов. Такие игры могут понравиться и взрослым. Игры с этим рейтингом могут содержать минимальное насилие, в основном «мультяшного» характера. Первоначально «K-A» («Kids to Adults»).
- «E10+» («Everyone 10 and older») — «Для всех от 10 лет и старше»: Проекты с данным рейтингом могут содержать больше мультипликационного или мягкого насилия, или несколько откровенные сцены, или минимальное количество крови. Рейтинг был принят ESRB 2 марта 2005 года.
- «T» («Teen») — «Подросткам»: Игра подходит для лиц от 13 лет. Проекты из данной категории могут содержать насилие, непристойные сцены, грубый юмор, в меру откровенное сексуальное содержимое, кровь или нечастое использование ненормативной лексики.
- «M» («Mature») — «Для взрослых»: Материалы игры не подходят для лиц младше 17 лет. Проекты с данным рейтингом могут содержать жестокое насилие, большое количество крови с расчленением, непристойные сексуальные сцены или грубую ненормативную лексику.
- «AO» («Adults Only 18+») — «Только для взрослых»: Содержание игры только для взрослых старше 18 лет. Продукты из данной категории могут содержать длительные сцены жестокого насилия и/или очень откровенное сексуальное содержимое.
- «RP» («Rating Pending») — «Рейтинг ожидается»: Продукт был отправлен в ESRB и ожидает присвоения рейтинга. Данный логотип используется только на рекламных презентациях и в демо-версиях игр до официальной даты выпуска в продажу.
- «RP 17+» («Rating Pending») — «Рейтинг ожидается — примерно 17+»: Продукт отправлен ESRB на оценку, но примерное содержание близко к рейтингу «M». Данная маркировка была введена с 2021 г. и распространяется на демо или презентационный вариант.
print('Позиции рейтинга ESRB в датафрейме:')
print(games['Rating'].unique())
Позиции рейтинга ESRB в датафрейме: ['E' nan 'M' 'T' 'E10+' 'K-A' 'AO' 'EC' 'RP']
В рейтингах присутствуют пропуски и устаревшее значение K-A
, которое для актуализации требуется заменить на E
. Также есть пропуски, которые, возможно, относятся к RP
(Rating Pending — Рейтинг ожидается).
print('Количество значений "K-A" в столбце с рейтингом:', games.loc[games['Rating'] == 'K-A', 'Rating'].count())
Количество значений "K-A" в столбце с рейтингом: 3
print('Количество пропусков в столбце с рейтингом:', games['Rating'].isna().sum())
print(f"Эти пропуски составляют {round((games['Rating'].isna().sum() / (games['Rating'].count() + games['Rating'].isna().sum())) * 100, 2)}% от всего количества значений с рейтингом")
print('Примеры строк с пропусками в столбце с рейтингом:')
games.loc[games['Rating'].isna()].head(10)
Количество пропусков в столбце с рейтингом: 6766 Эти пропуски составляют 40.48% от всего количества значений с рейтингом Примеры строк с пропусками в столбце с рейтингом:
Name | Platform | Year_of_Release | Genre | NA_sales | EU_sales | JP_sales | Other_sales | Critic_Score | User_Score | Rating | |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | Super Mario Bros. | NES | 1985.0 | Platform | 29.08 | 3.58 | 6.81 | 0.77 | NaN | NaN | NaN |
4 | Pokemon Red/Pokemon Blue | GB | 1996.0 | Role-Playing | 11.27 | 8.89 | 10.22 | 1.00 | NaN | NaN | NaN |
5 | Tetris | GB | 1989.0 | Puzzle | 23.20 | 2.26 | 4.22 | 0.58 | NaN | NaN | NaN |
9 | Duck Hunt | NES | 1984.0 | Shooter | 26.93 | 0.63 | 0.28 | 0.47 | NaN | NaN | NaN |
10 | Nintendogs | DS | 2005.0 | Simulation | 9.05 | 10.95 | 1.93 | 2.74 | NaN | NaN | NaN |
12 | Pokemon Gold/Pokemon Silver | GB | 1999.0 | Role-Playing | 9.00 | 6.18 | 7.20 | 0.71 | NaN | NaN | NaN |
18 | Super Mario World | SNES | 1990.0 | Platform | 12.78 | 3.75 | 3.54 | 0.55 | NaN | NaN | NaN |
20 | Pokemon Diamond/Pokemon Pearl | DS | 2006.0 | Role-Playing | 6.38 | 4.46 | 6.04 | 1.36 | NaN | NaN | NaN |
21 | Super Mario Land | GB | 1989.0 | Platform | 10.83 | 2.71 | 4.18 | 0.42 | NaN | NaN | NaN |
22 | Super Mario Bros. 3 | NES | 1988.0 | Platform | 9.54 | 3.44 | 3.84 | 0.46 | NaN | NaN | NaN |
Всего наблюдается 6766 пропусков в столбце Rating
, что составляет 40.48% от всего количества значений. Вывод части датафрейма показал, что пропуски в столбце Critic_Score
иногда совпадают с пропусками в столбцах Critic_Score
и User_Score
.
# Датафрейс содержащий одновременные пропуски
# в столбцах 'Rating', 'Critic_Score' и 'User_Score'
rating_isna = games.loc[
(games['Rating'].isna()) &
(games['Critic_Score'].isna()) &
(games['User_Score'].isna())
]
rating_isna.head()
Name | Platform | Year_of_Release | Genre | NA_sales | EU_sales | JP_sales | Other_sales | Critic_Score | User_Score | Rating | |
---|---|---|---|---|---|---|---|---|---|---|---|
1 | Super Mario Bros. | NES | 1985.0 | Platform | 29.08 | 3.58 | 6.81 | 0.77 | NaN | NaN | NaN |
4 | Pokemon Red/Pokemon Blue | GB | 1996.0 | Role-Playing | 11.27 | 8.89 | 10.22 | 1.00 | NaN | NaN | NaN |
5 | Tetris | GB | 1989.0 | Puzzle | 23.20 | 2.26 | 4.22 | 0.58 | NaN | NaN | NaN |
9 | Duck Hunt | NES | 1984.0 | Shooter | 26.93 | 0.63 | 0.28 | 0.47 | NaN | NaN | NaN |
10 | Nintendogs | DS | 2005.0 | Simulation | 9.05 | 10.95 | 1.93 | 2.74 | NaN | NaN | NaN |
print('Количество пропусков с стобцах с рейтингом и оценками:')
print(rating_isna.isna().sum())
Количество пропусков с стобцах с рейтингом и оценками: Name 2 Platform 0 Year_of_Release 85 Genre 2 NA_sales 0 EU_sales 0 JP_sales 0 Other_sales 0 Critic_Score 6621 User_Score 6621 Rating 6621 dtype: int64
В 85 строках пропуски в столбцах Rating
, Critic_Score
и User_Score
совпадают с пропусками в столбце Year_of_Release
. В двух строках из них они совпадают с пропусками в Name
.
print("Уникальные значения различных столбцов в строках с пропусками в 'Rating', 'Critic_Score' и 'User_Score'")
print()
print(f"Столбец 'Name' ({len(rating_isna['Name'].unique())} уникальных значений из {len(games['Name'].unique())}):")
print(rating_isna['Name'].unique())
print()
print(f"Столбец 'Platform' ({len(rating_isna['Platform'].unique())} уникальных значений из {len(games['Platform'].unique())}):")
print(rating_isna['Platform'].unique())
print()
print(f"Столбец 'Year_of_Release' ({len(rating_isna['Year_of_Release'].unique())} уникальных значений из {len(games['Year_of_Release'].unique())}):")
print(rating_isna['Year_of_Release'].unique())
print()
print(f"Столбец 'Genre' ({len(rating_isna['Genre'].unique())} уникальных значений из {len(games['Genre'].unique())}):")
print(rating_isna['Genre'].unique())
Уникальные значения различных столбцов в строках с пропусками в 'Rating', 'Critic_Score' и 'User_Score' Столбец 'Name' (5732 уникальных значений из 11560): ['Super Mario Bros.' 'Pokemon Red/Pokemon Blue' 'Tetris' ... 'Woody Woodpecker in Crazy Castle 5' 'LMA Manager 2007' 'Haitaka no Psychedelica'] Столбец 'Platform' (31 уникальных значений из 31): ['NES' 'GB' 'DS' 'SNES' 'GBA' 'PS4' '3DS' 'N64' 'X360' 'Wii' '2600' 'PS' 'XOne' 'GC' 'PS3' 'GEN' 'PC' 'PSP' 'WiiU' 'PS2' 'XB' 'DC' 'PSV' 'SAT' 'SCD' 'WS' 'NG' 'TG16' '3DO' 'GG' 'PCFX'] Столбец 'Year_of_Release' (38 уникальных значений из 38): [1985. 1996. 1989. 1984. 2005. 1999. 1990. 2006. 1988. 2002. 2010. 1998. 2015. 2013. 2009. 2014. 1992. 1993. 2004. 1994. 1997. 2012. 2007. 1982. 2016. 2003. 2011. 1986. 2000. 2001. 1995. 2008. 1991. 1981. 1987. 1980. 1983. nan] Столбец 'Genre' (13 уникальных значений из 13): ['Platform' 'Role-Playing' 'Puzzle' 'Shooter' 'Simulation' 'Action' 'Adventure' 'Racing' 'Misc' 'Sports' 'Fighting' 'Strategy' nan]
Не обнаружено какой-либо зависимости пропусков в Rating
, Critic_Score
и User_Score
от значений в столбцах Name
, Platform
, Year_of_Release
или Genre
. Согласно мнению пользователей (не экспертов) ресурса gaming.stackexchange.com отсутствие рейтинга может свидетельствовать о нежелании владельцев рейтинга ESRB устанавливать метки со своим рейтингом на играх, которые имеют очень разнообразное содержание для разных возрастных групп, которое зависит от определенных условий использования игры (https://gaming.stackexchange.com/questions/27940/why-doesnt-esrb-rate-online-games, 2023). Строки с подобными пропусками можно оставить в датафрейме для дальнейшего анализа. Отсутствие данных в них — это информация о том, что ни рейтинговое агентство ESRB, ни эксперты, ни пользователи, не захотели или не смогли охарактеризовать эти игры.
print("Медианные значения продаж в разных регионах при пропусках в 'Rating', 'Critic_Score', 'User_Score' и 'Year_of_Release'")
print()
print('Продажи в Северной Америке:', rating_isna.loc[rating_isna['Year_of_Release'].isna(), 'NA_sales'].median())
print('Продажи в Европе:', rating_isna.loc[rating_isna['Year_of_Release'].isna(), 'EU_sales'].median())
print('Продажи в Японии:', rating_isna.loc[rating_isna['Year_of_Release'].isna(), 'JP_sales'].median())
print('Продажи в других регионах:', rating_isna.loc[rating_isna['Year_of_Release'].isna(), 'Other_sales'].median())
Медианные значения продаж в разных регионах при пропусках в 'Rating', 'Critic_Score', 'User_Score' и 'Year_of_Release' Продажи в Северной Америке: 0.01 Продажи в Европе: 0.0 Продажи в Японии: 0.0 Продажи в других регионах: 0.0
В тех же случаях, где пропуски в Rating
, Critic_Score
и User_Score
совпадают с пропусками в Year_of_Release
, это может означать, что игра еще не выпущена в продажу. Это подтверждается нулевыми медианными продажами почти во всех регионах. Наличие медианных продаж в Северной Америке в размере 10 тыс. копий игр может означать их продажу с целью изучения рынка. Строкам с подобными данными можно дать рейтинг no_ESRB
, что даст возможность анализировать эти строки. Либо, удалить их из датафрейма, т.к. можно оспорить их полезность для дальнейшего анализа.
Итоги предварительного анализа данных¶
В датафрейме всего 11 столбцов и 16715 строк. 7 столбцов содержат пропуски. Вес датафрейма 1.4 Мб. В данных наблюдаются пропуски. Строки с пропуском в названии игры требуется удалить, т.к. во многих аттрибутах этих объектов пропуски. Строки с игрой Madden NFL 13
, выпущенной в 2012 году на платформе PS3
желательно объеденить, т.к. данные в них частично дополняют друг друга. Названия столбцов в датафрейме выполнены не в «змеином» стиле. Можно изменить типы данных столбцов:
Year_of_Release
наuint16
, т.к. года являются четырёхзначными натуральными числами;NA_sales
,EU_sales
,JP_sales
,Other_sales
,Critic_Score
иUser_Score
наfloat16
, т.к. в этих столбцах использованы рациональные числа небольшой размерности.
О столбце ‘Rating’
В рейтингах присутствуют пропуски и устаревшее значение K-A
, которое для актуализации требуется заменить на E
.
Всего наблюдается 6766 пропусков в столбце Rating
, что составляет 40.48% от всего количества значений. Вывод части датафрейма показал, что пропуски в столбце Critic_Score
иногда совпадают с пропусками в столбцах Critic_Score
и User_Score
.
Не обнаружено какой-либо зависимости пропусков в Rating
, Critic_Score
и User_Score
от значений в столбцах Name
, Platform
, Year_of_Release
или Genre
. Согласно мнению пользователей (не экспертов) ресурса gaming.stackexchange.com отсутствие рейтинга может свидетельствовать о нежелании владельцев рейтинга ESRB устанавливать метки со своим рейтингом на играх, которые имеют очень разнообразное содержание для разных возрастных групп, которое зависит от определенных условий использования игры (https://gaming.stackexchange.com/questions/27940/why-doesnt-esrb-rate-online-games, 2023). Строки с подобными пропусками можно оставить в датафрейме для дальнейшего анализа. Отсутствие данных в них — это информация о том, что ни рейтинговое агентство ESRB, ни эксперты, ни пользователи, не захотели или не смогли охарактеризовать эти игры.
В тех же случаях, где пропуски в Rating
, Critic_Score
и User_Score
совпадают с пропусками в Year_of_Release
, это может означать, что игра еще не выпущена в продажу. Это подтверждается нулевыми медианными продажами почти во всех регионах. Наличие медианных продаж в Северной Америке в размере 10 тыс. копий игр может означать их продажу с целью изучения рынка. Строкам с подобными данными можно дать рейтинг no_ESRB
, что даст возможность анализировать эти строки. Либо, удалить их из датафрейма, т.к. можно оспорить их полезность для дальнейшего анализа.
Шаг 2. Подготовка данных¶
Замените названия столбцов (приведите к нижнему регистру)¶
games.columns = games.columns.str.lower()
games.head()
name | platform | year_of_release | genre | na_sales | eu_sales | jp_sales | other_sales | critic_score | user_score | rating | |
---|---|---|---|---|---|---|---|---|---|---|---|
0 | Wii Sports | Wii | 2006.0 | Sports | 41.36 | 28.96 | 3.77 | 8.45 | 76.0 | 8 | E |
1 | Super Mario Bros. | NES | 1985.0 | Platform | 29.08 | 3.58 | 6.81 | 0.77 | NaN | NaN | NaN |
2 | Mario Kart Wii | Wii | 2008.0 | Racing | 15.68 | 12.76 | 3.79 | 3.29 | 82.0 | 8.3 | E |
3 | Wii Sports Resort | Wii | 2009.0 | Sports | 15.61 | 10.93 | 3.28 | 2.95 | 80.0 | 8 | E |
4 | Pokemon Red/Pokemon Blue | GB | 1996.0 | Role-Playing | 11.27 | 8.89 | 10.22 | 1.00 | NaN | NaN | NaN |
Все названия столбцов привередны к нижнему регистру для соответствия «змеиному стилю».
Обработка пропусков¶
games['year_of_release'].unique()
array([2006., 1985., 2008., 2009., 1996., 1989., 1984., 2005., 1999., 2007., 2010., 2013., 2004., 1990., 1988., 2002., 2001., 2011., 1998., 2015., 2012., 2014., 1992., 1997., 1993., 1994., 1982., 2016., 2003., 1986., 2000., nan, 1995., 1991., 1981., 1987., 1980., 1983.])
В year_of_release
есть пропуски nan
, которые вызовут ошибку при конвертации в uint16
. Также строки с nan
в year_of_release
неинформативны для анализа. В том числе, это связано с тем, пропуски в столбце year_of_release
одновременно совпадают со строками, содеражщими пропуски в rating
, critic_score
и user_score
, в которых, вероятнее всего, содержаться данные об играх, которые еще не поступили в полномасштабную продражу. Подобные данные не требуются для дальнейшего анализа.
(games['year_of_release'].isna().count() - games['year_of_release'].dropna().count()) / games['year_of_release'].isna().count()
0.01609332934489979
Если удалить строки с пропусками в year_of_release
, то будет потерено всего 1.61% строк с данными. Это не является кричтиным для анализа и потому, эти строки будут удалены.
games = games.dropna(subset=['year_of_release'])
print(games['year_of_release'].unique())
print()
print(games.info())
[2006. 1985. 2008. 2009. 1996. 1989. 1984. 2005. 1999. 2007. 2010. 2013. 2004. 1990. 1988. 2002. 2001. 2011. 1998. 2015. 2012. 2014. 1992. 1997. 1993. 1994. 1982. 2016. 2003. 1986. 2000. 1995. 1991. 1981. 1987. 1980. 1983.] <class 'pandas.core.frame.DataFrame'> Int64Index: 16446 entries, 0 to 16714 Data columns (total 11 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 name 16444 non-null object 1 platform 16446 non-null object 2 year_of_release 16446 non-null float64 3 genre 16444 non-null object 4 na_sales 16446 non-null float64 5 eu_sales 16446 non-null float64 6 jp_sales 16446 non-null float64 7 other_sales 16446 non-null float64 8 critic_score 7983 non-null float64 9 user_score 9839 non-null object 10 rating 9768 non-null object dtypes: float64(6), object(5) memory usage: 1.5+ MB None
В столбце year_of_release
после удаления пропусков остались только информативные строки с указанием года релиза игр.
games['user_score'].unique()
array(['8', nan, '8.3', '8.5', '6.6', '8.4', '8.6', '7.7', '6.3', '7.4', '8.2', '9', '7.9', '8.1', '8.7', '7.1', '3.4', '5.3', '4.8', '3.2', '8.9', '6.4', '7.8', '7.5', '2.6', '7.2', '9.2', '7', '7.3', '4.3', '7.6', '5.7', '5', '9.1', '6.5', 'tbd', '8.8', '6.9', '9.4', '6.8', '6.1', '6.7', '5.4', '4', '4.9', '4.5', '9.3', '6.2', '4.2', '6', '3.7', '4.1', '5.8', '5.6', '5.5', '4.4', '4.6', '5.9', '3.9', '3.1', '2.9', '5.2', '3.3', '4.7', '5.1', '3.5', '2.5', '1.9', '3', '2.7', '2.2', '2', '9.5', '2.1', '3.6', '2.8', '1.8', '3.8', '0', '1.6', '9.6', '2.4', '1.7', '1.1', '0.3', '1.5', '0.7', '1.2', '2.3', '0.5', '1.3', '0.2', '0.6', '1.4', '0.9', '1', '9.7'], dtype=object)
В столбце user_score
есть значение tbd
, которое вызовет ошибку при конвертации в float16
.
# Замена 'tbd' на 'np.nan'
# для конвертации столбца в 'float16'
games['user_score'] = pd.to_numeric(
games['user_score'].replace('tbd', np.nan),
downcast='float'
)
games.head()
name | platform | year_of_release | genre | na_sales | eu_sales | jp_sales | other_sales | critic_score | user_score | rating | |
---|---|---|---|---|---|---|---|---|---|---|---|
0 | Wii Sports | Wii | 2006.0 | Sports | 41.36 | 28.96 | 3.77 | 8.45 | 76.0 | 8.0 | E |
1 | Super Mario Bros. | NES | 1985.0 | Platform | 29.08 | 3.58 | 6.81 | 0.77 | NaN | NaN | NaN |
2 | Mario Kart Wii | Wii | 2008.0 | Racing | 15.68 | 12.76 | 3.79 | 3.29 | 82.0 | 8.3 | E |
3 | Wii Sports Resort | Wii | 2009.0 | Sports | 15.61 | 10.93 | 3.28 | 2.95 | 80.0 | 8.0 | E |
4 | Pokemon Red/Pokemon Blue | GB | 1996.0 | Role-Playing | 11.27 | 8.89 | 10.22 | 1.00 | NaN | NaN | NaN |
После обработки пропусков данные отображаются корректно.
# Удаление пропусков в столбце 'name'
games = games.dropna(subset=['name'])
games.info()
<class 'pandas.core.frame.DataFrame'> Int64Index: 16444 entries, 0 to 16714 Data columns (total 11 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 name 16444 non-null object 1 platform 16444 non-null object 2 year_of_release 16444 non-null float64 3 genre 16444 non-null object 4 na_sales 16444 non-null float64 5 eu_sales 16444 non-null float64 6 jp_sales 16444 non-null float64 7 other_sales 16444 non-null float64 8 critic_score 7983 non-null float64 9 user_score 7463 non-null float32 10 rating 9768 non-null object dtypes: float32(1), float64(6), object(4) memory usage: 1.4+ MB
После удаления пропусков сравнялось количество объектов без пропусков в основных аттрибутах.
# Пропущенные рейтинги заменяются на
# рейтинг RP (Rating Pending - Рейтинг ожидается)
games['rating'] = games['rating'].fillna('no_ESRB')
games.loc[games['rating'] == 'RP'].info()
<class 'pandas.core.frame.DataFrame'> Int64Index: 1 entries, 14270 to 14270 Data columns (total 11 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 name 1 non-null object 1 platform 1 non-null object 2 year_of_release 1 non-null float64 3 genre 1 non-null object 4 na_sales 1 non-null float64 5 eu_sales 1 non-null float64 6 jp_sales 1 non-null float64 7 other_sales 1 non-null float64 8 critic_score 1 non-null float64 9 user_score 1 non-null float32 10 rating 1 non-null object dtypes: float32(1), float64(6), object(4) memory usage: 92.0+ bytes
Пропущенные рейтинги заменены на значение no_ESRB
. Данная «заглушка» для пропусков нужна для анализа строк с этим рейтингом.
Результаты удаления пропусков
В датасете заменены или удалены критичные пропуски в данных, которые не позволили бы конвертировать столбцы в более приемлемые типы данных, а также не нужны были при дальнейшем анализе. Так, в year_of_release
пропуски nan
были удалены, что позволило избавиться от строк с данными об играх, которые еще не поступили в полномасштабную продажу, а в user_score
значения tbd
заменены на np.nan
. Также удалены объекты с пропусками в аттрибуте name
.
Пропущенные рейтинги заменены на рейтинг RP (Rating Pending — Рейтинг ожидается). Исходим из того, что не классифицированная по рейтингу игра и ожидающая рейтинга — это одно и тоже.
В остальных столбцах пропуски не изменены для корректного общего представления о данных при расчётах. В каждом отдельном случае можно исключить из расчётов строки с пропусками в столбцах, участвующих в расчётах.
Обработка строк с неявными дубликатами¶
# Просмотр строк с неявными дубликатами,
# выявленными при первичном анализе данных
games.loc[
((games['name'] == 'Madden NFL 13') &
(games['platform'] == 'PS3') &
(games['year_of_release'] == 2012))
]
name | platform | year_of_release | genre | na_sales | eu_sales | jp_sales | other_sales | critic_score | user_score | rating | |
---|---|---|---|---|---|---|---|---|---|---|---|
604 | Madden NFL 13 | PS3 | 2012.0 | Sports | 2.11 | 0.22 | 0.0 | 0.23 | 83.0 | 5.5 | E |
16230 | Madden NFL 13 | PS3 | 2012.0 | Sports | 0.00 | 0.01 | 0.0 | 0.00 | 83.0 | 5.5 | E |
Строку 16230 с неявным дубликатом удалять нельзя, т.к. она содержит данные о продаже в Европе. Для объединения данных строк с неявными дубликатами требуется значение eu_sales
из строки 16230 прибавить к значению eu_sales
в строке 604. После этого строку 16230 требуется удалить.
# Сложение значений 'eu_sales' в строках с неявными дубликатами
#games.loc[games.index == 604, 'eu_sales'] += games.loc[games.index == 16230, 'eu_sales']
games.loc[games.index == 604, 'eu_sales'].add(games.loc[games.index == 16230, 'eu_sales'])
#games.loc[games.index == 604, 'eu_sales'] = games.loc[games.index == 604, 'eu_sales'] + games.loc[games.index == 16230, 'eu_sales']
# Удаление строки дубликата
games = games.loc[games.index != 16230]
# Проверка наличия дубликата
games.loc[
(games['name'] == 'Madden NFL 13') &
(games['platform'] == 'PS3') &
(games['year_of_release'] == 2012)
]
name | platform | year_of_release | genre | na_sales | eu_sales | jp_sales | other_sales | critic_score | user_score | rating | |
---|---|---|---|---|---|---|---|---|---|---|---|
604 | Madden NFL 13 | PS3 | 2012.0 | Sports | 2.11 | 0.22 | 0.0 | 0.23 | 83.0 | 5.5 | E |
Неявные дубликаты строк с игрой Madden NFL 13
на платформе PS3
, выпущенной в 2012 году, обработаны путем сложения данных о продажах в Европе и удаления второй повторяющейся строки.
Далее будут обработаны рейтинги со значениями K-A
и E
.
# Проверка количества значений 'E' в столбце 'rating'
print('Изначальное количество значений "E" в столбце "rating":', games.loc[games['rating'] == 'E', 'rating'].count())
# Замена устаревших значений 'K-A' на 'E' в столбце 'rating'
games.loc[games['rating'] == 'K-A', 'rating'] = 'E'
# Повторная проверка количества значений 'E' в столбце 'rating'
print('Количество значений "E" в столбце "rating" после замены "K-A":', games.loc[games['rating'] == 'E', 'rating'].count())
Изначальное количество значений "E" в столбце "rating": 3920 Количество значений "E" в столбце "rating" после замены "K-A": 3923
Три устаревших значения рейтинга K-A
в столбце rating
заменено на E
.
Преобразование данных в нужные типы¶
При первичном анализа данных были выявлены 7 столбцов, в которых можно понизить разрядность данных, путем их конвертации.
# Конвертация в 'uint16'
games['year_of_release'] = games['year_of_release'].astype('uint16')
#games['year_of_release'] = pd.DatetimeIndex(games['year_of_release']).year
# Конвертация в 'float16'
for i in ['na_sales', 'eu_sales', 'jp_sales', 'other_sales', 'critic_score', 'user_score']:
games[i] = games[i].astype('float16')
games.info()
<class 'pandas.core.frame.DataFrame'> Int64Index: 16443 entries, 0 to 16714 Data columns (total 11 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 name 16443 non-null object 1 platform 16443 non-null object 2 year_of_release 16443 non-null uint16 3 genre 16443 non-null object 4 na_sales 16443 non-null float16 5 eu_sales 16443 non-null float16 6 jp_sales 16443 non-null float16 7 other_sales 16443 non-null float16 8 critic_score 7982 non-null float16 9 user_score 7462 non-null float16 10 rating 16443 non-null object dtypes: float16(6), object(4), uint16(1) memory usage: 867.1+ KB
Типы данных в 7 столбцах изменены. Размер датафрейма уменьшен почти в 2 раза до 867.1 Кб.
games.head()
name | platform | year_of_release | genre | na_sales | eu_sales | jp_sales | other_sales | critic_score | user_score | rating | |
---|---|---|---|---|---|---|---|---|---|---|---|
0 | Wii Sports | Wii | 2006 | Sports | 41.375000 | 28.953125 | 3.769531 | 8.453125 | 76.0 | 8.000000 | E |
1 | Super Mario Bros. | NES | 1985 | Platform | 29.078125 | 3.580078 | 6.808594 | 0.770020 | NaN | NaN | no_ESRB |
2 | Mario Kart Wii | Wii | 2008 | Racing | 15.679688 | 12.757812 | 3.789062 | 3.289062 | 82.0 | 8.296875 | E |
3 | Wii Sports Resort | Wii | 2009 | Sports | 15.609375 | 10.929688 | 3.279297 | 2.949219 | 80.0 | 8.000000 | E |
4 | Pokemon Red/Pokemon Blue | GB | 1996 | Role-Playing | 11.273438 | 8.890625 | 10.218750 | 1.000000 | NaN | NaN | no_ESRB |
Значения в столбцах с измененным типом данных — приемлемые.
Подсчет суммарных продаж игр во всех регионах в отдельном столбце датафрейма¶
# Миллионов проданных копий игр
games['total_sales'] = games.loc[:, [
'na_sales',
'eu_sales',
'jp_sales',
'other_sales'
]].sum(axis=1)
# Корректировка типа данных для дальнейших расчетов
games['total_sales'] = games['total_sales'].astype('float64')
games.head()
name | platform | year_of_release | genre | na_sales | eu_sales | jp_sales | other_sales | critic_score | user_score | rating | total_sales | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | Wii Sports | Wii | 2006 | Sports | 41.375000 | 28.953125 | 3.769531 | 8.453125 | 76.0 | 8.000000 | E | 82.500 |
1 | Super Mario Bros. | NES | 1985 | Platform | 29.078125 | 3.580078 | 6.808594 | 0.770020 | NaN | NaN | no_ESRB | 40.250 |
2 | Mario Kart Wii | Wii | 2008 | Racing | 15.679688 | 12.757812 | 3.789062 | 3.289062 | 82.0 | 8.296875 | E | 35.500 |
3 | Wii Sports Resort | Wii | 2009 | Sports | 15.609375 | 10.929688 | 3.279297 | 2.949219 | 80.0 | 8.000000 | E | 32.750 |
4 | Pokemon Red/Pokemon Blue | GB | 1996 | Role-Playing | 11.273438 | 8.890625 | 10.218750 | 1.000000 | NaN | NaN | no_ESRB | 31.375 |
games.info()
<class 'pandas.core.frame.DataFrame'> Int64Index: 16443 entries, 0 to 16714 Data columns (total 12 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 name 16443 non-null object 1 platform 16443 non-null object 2 year_of_release 16443 non-null uint16 3 genre 16443 non-null object 4 na_sales 16443 non-null float16 5 eu_sales 16443 non-null float16 6 jp_sales 16443 non-null float16 7 other_sales 16443 non-null float16 8 critic_score 7982 non-null float16 9 user_score 7462 non-null float16 10 rating 16443 non-null object 11 total_sales 16443 non-null float64 dtypes: float16(6), float64(1), object(4), uint16(1) memory usage: 995.6+ KB
Успешно добавлен стобец с total_sales
с типом данных float64
, содержащий суммы всех продаж каждого релиза по всем регионам, включая other_sales
, измеряемая в миллионах копий игр.
Итоги подготовки данных¶
В датафрейме заменены и удалены критичные пропуски в данных, которые не позволили бы конвертировать столбцы в более приемлемые типы данных. Так, в user_score
значения tbd
заменены на np.nan
, а в year_of_release
пропуски nan
были удалены. Последнее позволило избавиться от строк с данными об играх, которые еще не поступили в полномасштабную продажу. Также удалены строки с пропусками в столбце name
. После удаления строк с пропусками потеряно только 1.6% всех строк датафрейма, что не является критичным для анализа. В остальных столбцах пропуски не изменены для корректного общего представления о данных при расчётах. В каждом отдельном случае можно исключить из расчётов строки с пропусками в столбцах, участвующих в расчётах.
Пропущенные рейтинги заменены на рейтинг RP (Rating Pending — Рейтинг ожидается). Исходим из того, что не классифицированная по рейтингу игра и ожидающая рейтинга — это одно и тоже.
Неявные дубликаты строк с игрой Madden NFL 13
на платформе PS3
, выпущенной в 2012 году, обработаны путем сложения данных о продажах в Европе и удаления второй повторяющейся строки. Три устаревших значения рейтинга K-A
в столбце rating
заменено на E
.
Типы данных в 7 столбцах изменены. Благодаря этому размер датафрейма уменьшен почти в 2 раза до 867.3 Кб. Успешно добавлен стобец с total_sales
с типом данных float64
, содержащий суммы всех продаж каждого релиза по всем регионам, включая other_sales
, измеряемая в миллионах копий игр. Все названия столбцов датафрейма привередны к нижнему регистру для соответствия «змеиному стилю».
Причины появления пропусков
Пропуски в столбце year_of_release
могли быть вызваны либо небрежностью ввода данных (если в большинстве других столбцов есть данные), либо тем, что игра создана, но еще не выпущена в продажу (если отсутствуют данные о продажах и рейтинге). В любом случае, без этих данных затрудняется анализ объектов и они могут быть удалены.
Одновременные пропуски в столбцах name
и platform
, вероятнее всего вызваны ошибкой ввода данных, т.к. в этом случае объект не возможно идентифицировать и его наличие бессмысленно.
Пропуски в столбцах с продажами в определенном регионе могут означать отсутствие продаж. Пропуски в столбцах с оценками пользователей или экспертов может означать, что эксперты и пользователи не оствили свои отзывы по этим объектам. Пропуски в столбцах с рейтингом при наличии данных о годе выпуска релиза могут означать отсутствие желания рейтинговое агентства по каким-либо причинам давать рейтинг объекту.
# Комментарий ревьюера
# Посмотрим, что осталось
temp = games.copy()
list_c = ['name', 'platform', 'year_of_release', 'genre', 'critic_score', 'user_score', 'rating']
print(temp.info())
for col_l in list_c:
print('-'* 25)
print(col_l, temp[col_l].sort_values().unique())
print(col_l,': кол-во NaN',temp[col_l].isna().sum(),
', процент NaN', round(temp[col_l].isna().mean()*100,2),'%')
<class 'pandas.core.frame.DataFrame'> Int64Index: 16443 entries, 0 to 16714 Data columns (total 12 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 name 16443 non-null object 1 platform 16443 non-null object 2 year_of_release 16443 non-null uint16 3 genre 16443 non-null object 4 na_sales 16443 non-null float16 5 eu_sales 16443 non-null float16 6 jp_sales 16443 non-null float16 7 other_sales 16443 non-null float16 8 critic_score 7982 non-null float16 9 user_score 7462 non-null float16 10 rating 16443 non-null object 11 total_sales 16443 non-null float64 dtypes: float16(6), float64(1), object(4), uint16(1) memory usage: 995.6+ KB None ------------------------- name [' Beyblade Burst' ' Fire Emblem Fates' " Frozen: Olaf's Quest" ... 'uDraw Studio' 'uDraw Studio: Instant Artist' '¡Shin Chan Flipa en colores!'] name : кол-во NaN 0 , процент NaN 0.0 % ------------------------- platform ['2600' '3DO' '3DS' 'DC' 'DS' 'GB' 'GBA' 'GC' 'GEN' 'GG' 'N64' 'NES' 'NG' 'PC' 'PCFX' 'PS' 'PS2' 'PS3' 'PS4' 'PSP' 'PSV' 'SAT' 'SCD' 'SNES' 'TG16' 'WS' 'Wii' 'WiiU' 'X360' 'XB' 'XOne'] platform : кол-во NaN 0 , процент NaN 0.0 % ------------------------- year_of_release [1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016] year_of_release : кол-во NaN 0 , процент NaN 0.0 % ------------------------- genre ['Action' 'Adventure' 'Fighting' 'Misc' 'Platform' 'Puzzle' 'Racing' 'Role-Playing' 'Shooter' 'Simulation' 'Sports' 'Strategy'] genre : кол-во NaN 0 , процент NaN 0.0 % ------------------------- critic_score [13. 17. 19. 20. 21. 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. nan] critic_score : кол-во NaN 8461 , процент NaN 51.46 % ------------------------- user_score [0. 0.2 0.3 0.5 0.6 0.7 0.9 1. 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 2. 2.1 2.2 2.3 2.4 2.5 2.6 2.7 2.8 2.9 3. 3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 4. 4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8 4.9 5. 5.1 5.2 5.3 5.4 5.5 5.6 5.7 5.8 5.9 6. 6.1 6.2 6.3 6.4 6.5 6.6 6.7 6.8 6.9 7. 7.1 7.2 7.3 7.4 7.5 7.6 7.7 7.8 7.9 8. 8.1 8.2 8.3 8.4 8.5 8.6 8.7 8.8 8.9 9. 9.1 9.2 9.3 9.4 9.5 9.6 9.7 nan] user_score : кол-во NaN 8981 , процент NaN 54.62 % ------------------------- rating ['AO' 'E' 'E10+' 'EC' 'M' 'RP' 'T' 'no_ESRB'] rating : кол-во NaN 0 , процент NaN 0.0 %
Шаг 3. Исследовательский анализ данных¶
Датасет содержит данные за несколько десятилетий. Важны ли данные за все периоды? Предположим, что существует 2 подхода к анализу исторических данных.
Первый подход. История циклична и требуется проанализировать исторические данные для выявления закономерностей и циклов.
Второй подход. В реальности на появление данных действует множество факторов и в каждый отдельный момент времени комбинация всего множества факторов почти всегда уникальна, тем более с учётом постоянного развития ситуации вокруг данных. Если это так, то анализ исторических данных не даёт точного ответа на вопрос, что будет с данными дальше. Однако, такую информацию можно отчасти получить из анализа анамалий в данных.
Объединяя оба подхода можно прийти к идее о том, что информацию о закономерности и цикличности значений во времени, полученную в результате анализа исторических данных, а также информацию о текущих анамалиях, можно использовать с определенной долей вероятностей при прогнозировании будущих значений данных. Иключением являются строки с пропусками в year_of_release
, которые удалены из датафрейма.
Количество игр, выпускаемых в разные годы¶
# Диаграммы свродных данных о продажах
# (количество релизов, общая сумма продаж, медиана продаж)
games.pivot_table(
index='year_of_release',
values='total_sales',
aggfunc=('count', 'sum', 'median')
).rename(columns={
'count':'количество релизов',
'sum':'общая сумма колличества продаж (млн.)',
'median':'медиана колличества продаж одного релиза (млн.)'
}).plot(
subplots=True,
layout=(3, 1),
grid=True,
xlabel='Годы релизов'
);
Наблюдается плавный рост количества релизов игр от года к году с 1980 по 2008 год. Затем наблюдается спад. Аналогично ведёт себя общее количество продаж копий игр в исследуемых регионах.
Однако, этой тенденции не подвержены медианные значения миллионов проданных копий игр одного релиза в год. До 1990 наблюдалась оносительно высокая волотильность. Затем до 1995 года был резкий спад с коррекцией. После этого наблюдается стагнация с очень медленным спадом.
Изменения продаж по платформам.¶
Выберите платформы с наибольшими суммарными продажами и постройте распределение по годам. За какой характерный срок появляются новые и исчезают старые платформы?
# Количество релизов игр в зависимости от платформы и года
total_relaese = games.sort_values(by='total_sales').pivot_table(
index='platform',
columns='year_of_release',
values='total_sales',
aggfunc='count'
)
# Тепловая карта количества релизов игр на разных платформах в разные годы
ax = sns.heatmap(total_relaese)
ax.set(
title='Тепловая карта количества релизов игр на разных платформах в разные годы',
ylabel='Платформы',
xlabel='Годы'
);