Coding/EDA / 캐글 EDA-Video game sales.md

캐글 EDA-Video game sales

조회

https://www.kaggle.com/datasets/gregorut/videogamesales

 

Video Game Sales

Analyze sales data from more than 16,500 games.

www.kaggle.com

본인은 겜덕후다. 자타공인 겜덕후이고 모바일 피씨 콘솔 할 것 없이 어지간한 게임은 다 했으며 가끔 무지하게 주관적인 리뷰를 올리기도 하고 집에는 각종 노랑뚱띵이와 굿즈들이 가득한.

 

그런데 비디오 게임 판매량 데이터??? 야이씨 이건 겜덕후로써 못참지! 해서 제미나이를 부려먹었다.


모듈

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

# 그래프 기본 테마 설정
sns.set_theme(palette="icefire", style="darkgrid", font_scale=1)
sns.color_palette("icefire", as_cmap=True)

# 그래프를 그리기 위한 기본 설정
plt.rcParams['font.family'] = 'NanumSquare'
# plt.rcParams['font.family'] = 'AppleGothic'
plt.rcParams['figure.figsize'] = 12, 9
plt.rcParams['font.size'] = 16
plt.rcParams['axes.unicode_minus'] = False

딱 필요한 것만 있음.


데이터 정보 확인

df.info()

video_df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 16598 entries, 0 to 16597
Data columns (total 11 columns):
 #   Column        Non-Null Count  Dtype  
---  ------        --------------  -----  
 0   Rank          16598 non-null  int64  
 1   Name          16598 non-null  object 
 2   Platform      16598 non-null  object 
 3   Year          16327 non-null  float64
 4   Genre         16598 non-null  object 
 5   Publisher     16540 non-null  object 
 6   NA_Sales      16598 non-null  float64
 7   EU_Sales      16598 non-null  float64
 8   JP_Sales      16598 non-null  float64
 9   Other_Sales   16598 non-null  float64
 10  Global_Sales  16598 non-null  float64
dtypes: float64(6), int64(1), object(4)
memory usage: 1.4+ MB

저기 몇개 카운트 안 맞는 것 같다고? 결측값이 껴있으니까요.

 

df.describe()

video_df.describe()

여기 들어있다고 다 수치형인 건 아니고 범주형이 있을 수도 있다. 숫자면 다 저따구로 나와서... 내가 볼 때 등수랑 년도는 수치형 아님.

 

video_df.describe(include='O')

범주형 데이터는 이렇게 나온다. 근데 왜 밝은 배경이냐고? 지금 깃헙에서 찍고 있으니까요.

 

df.isna().sum()

video_df.isna().sum() # 아놔 결측값..
Rank              0
Name              0
Platform          0
Year            271
Genre             0
Publisher        58
NA_Sales          0
EU_Sales          0
JP_Sales          0
Other_Sales       0
Global_Sales      0
dtype: int64

왜 슬픈 예감은 틀리질 않는가…

 

사실 결측값을 채우는데는 여러가지 방법이 있지만 가장 비효율적이고 개같이 오래걸리는 겁나 브루트포스 뺨치는 방식이 바로 직접 찾아서 채우는거다. 갑자기 그 얘기가 왜 나와요? 빠진거 찾아서 일일이 채웠으니까. 일부 발매일이 지역별로 다른 게임은 북미 기준으로 채웠다.

 

df.head()

video_df.head()

이건 걍 위에 다섯개 뭔지 보는거임.

 

df.columns

video_df.columns
Index(['Rank', 'Name', 'Platform', 'Year', 'Genre', 'Publisher', 'NA_Sales',
       'EU_Sales', 'JP_Sales', 'Other_Sales', 'Global_Sales'],
      dtype='object')

음 칼럼이 이렇게 있군.

 

범주 만들기

아 결측값이요? 그거 못올려 짤려. 쓸데없이 스크롤 길다고 백퍼 님들 짜증내요.

 

플랫폼 제조사별 범주

video_df['Platform'].unique() # 플랫폼 목록

롸? 데이터에 뭐가 어떻게 들어있길래 그래요? 저기에는 우리가 살면서 봐 왔던(혹은 사 왔던, 혹은 거쳐 간) 모든 게임기 기종이 들어있다. 엑박은 세종류인데 닌텐도만 해도 게임보이 GBA(게임보이 어드밴스) DS 3DS 위… 그래서 이걸 제조사별로 묶는 칼럼을 하나 만드는거다. 예를 들어서 플스는 소니 이런 식으로. 그래야 플엑닌 보지.

 

platform_map = {
    # Nintendo
    'Wii': 'Nintendo', 'NES': 'Nintendo', 'GB': 'Nintendo', 'DS': 'Nintendo', 
    'SNES': 'Nintendo', 'GBA': 'Nintendo', '3DS': 'Nintendo', 'N64': 'Nintendo', 
    'GC': 'Nintendo', 'WiiU': 'Nintendo',
    
    # Sony
    'PS3': 'Sony', 'PS2': 'Sony', 'PS4': 'Sony', 'PS': 'Sony', 
    'PSP': 'Sony', 'PSV': 'Sony',
    
    # Microsoft
    'X360': 'Microsoft', 'XB': 'Microsoft', 'XOne': 'Microsoft',
    
    # SEGA
    'GEN': 'Sega', 'DC': 'Sega', 'SAT': 'Sega', 'SCD': 'Sega', 'GG': 'Sega',
    
    # PC & Others
    'PC': 'PC', '2600': 'Atari', 'WS': 'Bandai', 'NG': 'SNK', 
    'TG16': 'NEC', '3DO': '3DO', 'PCFX': 'NEC'
}

# 'Platform_Vendor'라는 새로운 칼럼 만들기
video_df['Platform_Vendor'] = video_df['Platform'].map(platform_map)

나도 모르는 기기들이 많음. 발매됐을때 엄마반 아빠반이었던 것도 있음. (사유: 아직 감수분열도 안해서)

 

퍼블리셔 범주화

# {기존 퍼블리셔 이름: (계열사 그룹, 국적)}
pub_info_map = {
    # 일본계 (Japan)
    'Nintendo': ('Nintendo', 'Japan'),
    'Sony Computer Entertainment': ('Sony', 'Japan'),
    'Sony Computer Entertainment Europe': ('Sony', 'Japan'),
    'Sony Computer Entertainment America': ('Sony', 'Japan'),
    'Sega': ('Sega Sammy', 'Japan'),
    'Sammy Corporation': ('Sega Sammy', 'Japan'),
    'Capcom': ('Capcom', 'Japan'),
    'Konami Digital Entertainment': ('Konami', 'Japan'),
    'Namco Bandai Games': ('Bandai Namco', 'Japan'),
    'Banpresto': ('Bandai Namco', 'Japan'),
    'Square Enix': ('Square Enix', 'Japan'),
    'SquareSoft': ('Square Enix', 'Japan'),
    'Enix Corporation': ('Square Enix', 'Japan'),
    'Tecmo Koei': ('Koei Tecmo', 'Japan'),
    'Atlus': ('Sega Sammy', 'Japan'),
    
    # 북미계 (North America)
    'Activision': ('Activision Blizzard', 'North America'),
    'Activision Blizzard': ('Activision Blizzard', 'North America'),
    'Electronic Arts': ('EA', 'North America'),
    'EA Sports': ('EA', 'North America'),
    'Take-Two Interactive': ('Take-Two', 'North America'),
    'Rockstar Games': ('Take-Two', 'North America'), # 목록에 있을 경우
    'Microsoft Game Studios': ('Microsoft', 'North America'),
    'Bethesda Softworks': ('ZeniMax', 'North America'),
    'Warner Bros. Interactive Entertainment': ('Warner Bros', 'North America'),
    'THQ': ('THQ', 'North America'),
    
    # 유럽계 (Europe)
    'Ubisoft': ('Ubisoft', 'Europe'),
    'Ubisoft Annecy': ('Ubisoft', 'Europe'),
    'Codemasters': ('Codemasters', 'Europe'),
    '505 Games': ('Digital Bros', 'Europe'),
    'Deep Silver': ('Koch Media', 'Europe'),
    'Koch Media': ('Koch Media', 'Europe')
}

# 데이터프레임에 적용
video_df['Group'] = video_df['Publisher'].map(lambda x: pub_info_map.get(x, ('Others', 'Unknown'))[0])
video_df['Country'] = video_df['Publisher'].map(lambda x: pub_info_map.get(x, ('Others', 'Unknown'))[1])

별 건 아니고 게임 퍼블리셔를 제조사/국적으로 묶는거다. 저기 보면 코나미, 반다이 남코, 스퀘어 에닉스 보여요? 다 일본 회사잖음. 그거다. ㅇㅋ?

 

년도 그루핑

bins = [-1, 0, 1980, 1990, 2000, 2010, 2020, 2025]
labels = ['Unknown', 'Pre-1980', '1980s', '1990s', '2000s', '2010s', '2020s']

video_df['Era'] = pd.cut(video_df['Year'], bins=bins, labels=labels)

아니 뭐 이딴것까지 묶어요? 라고 생각하실 수도 있는데, 1990년대에 발매된 게임들을 볼 때 1990년부터 1999년까지 찾는 개노가다를 분석하는 코드에서 하고 싶지 않으면 할 수 있을 때 묶으십쇼.

 

플.엑.닌 삼국지

플.엑.닌은 플레이스테이션(공기청정기 아님), 엑스박스, 닌텐도다. 겜덕후들이라면 적어도 저 셋 중 하나 이상은 집에 있거나 구매 의사가 있을수도 있고, 겜덕후가 아니더라도 한번쯤은 들어봤으며, 특히 애 있는 집안에서 애들 시켜주면 껌뻑 죽는 그거 맞다. 얘네들이 하루아침에 응애 나 닌텐도! 이러고 나온 게 아니라 각각 태동기, 전성기, 흑역사(...)가 있고 특징이 있단말이죠. 그니까 함 보자.

 

얼마나 팔았나

# 전체 플랫폼(회사)별로 몇 개나 있나요?
video_df.groupby('Platform_Vendor')[['Rank']].count()

닌텐도 얘네는 뭐 게임 찍어내나요? 그게 아니라 닌텐도가 역사가 조낸 길어요... 나중에 얘기해드림.

 

# 플. 엑. 닌은 각각 얼마나 팔았을까? 
console_three = ['Nintendo','Sony','Microsoft'] # 엑박이 마소꺼예요.. 
video_df.query('Platform_Vendor in @console_three').groupby('Platform_Vendor')[['Rank']].count()

아니 그럼 마소는 왜이렇게 없어요? 빌형 뭐함? 마소(엑박)는 닌텐도나 소니(플스)에 비해 늦게 나온 애들이라 그래요.

 

# 년도별로는 얼마나 팔았음?
console_three = ['Nintendo','Sony','Microsoft']
video_df.query('Platform_Vendor in @console_three').groupby(['Platform_Vendor', 'Era'], observed=False)[['Global_Sales']].sum().sort_values(by=['Platform_Vendor', 'Global_Sales'], ascending=False)

년도별 판매량을 보면 닌텐도와 소니 둘 다 1980년부터 찍히지만 마소는 1990년대부터 찍히죠? 엑박이 플스, 닌텐도에 비해 후발주자다. 80년대 데이터를 비교해보면 소니보다 닌텐도가 더 많은데, 플.엑.닌중에는 닌텐도가 제일 먼저 나왔다.

 

# 다른 나라에서도 그럴까요?
# NA: 북미, EU: 유럽, JA: 일본, Other: 기타 
console_three = ['Nintendo','Sony','Microsoft']
video_df.query('Platform_Vendor in @console_three').groupby(['Platform_Vendor', 'Era'], observed=False)[['NA_Sales','EU_Sales','JP_Sales','Other_Sales','Global_Sales']].sum().sort_values(by=['Platform_Vendor','Era'], ascending=False)

칼럼은 왼쪽부터 북미, 유럽, 일본, 기타(한국도 포함인듯), 글로벌이다. 아니 닌텐도 북미에서 생각보다 많이 해먹었네?

 

import matplotlib.pyplot as plt
import seaborn as sns

# 1. 그래프용 데이터 준비 (Global 제외)
plot_df = df_2000s_region[['NA_Sales', 'EU_Sales', 'JP_Sales', 'Other_Sales']]

# 2. 그래프 그리기
# 'stacked=False'가 핵심입니다 (기본값이 False라 생략 가능)
ax = plot_df.plot(kind='bar', 
                    figsize=(12, 7), 
                    width=0.8,      # 막대 두께 조절
                    rot=0)          # x축 이름(Nintendo 등) 똑바로

# 3. 디테일 설정
plt.title('2000s Regional Sales Comparison: Sony vs Nintendo vs Microsoft', fontsize=16, pad=20)
plt.ylabel('Sales (Millions)', fontsize=12)
plt.xlabel('Platform Vendor', fontsize=12)
plt.legend(title='Region', fontsize=10)
plt.grid(axis='y', linestyle='--', alpha=0.5)

# 막대 위에 수치 표시 (가독성 업그레이드)
for p in ax.patches:
    ax.annotate(f'{p.get_height():.1f}', 
                (p.get_x() + p.get_width() / 2., p.get_height()), 
                ha = 'center', va = 'center', 
                xytext = (0, 7), 
                textcoords = 'offset points',
                fontsize=9)

plt.tight_layout()
plt.show()

소니는 유럽, 기타 지역에서 닌텐도를 앞섰고 엑박은 일본에서 맥을 못 추죠? 이건 마소가 단순히 늦게 시작해서가 아니라, 얘네들이 엑박을 내놓긴 했는데 일단 컨트롤러가 서양인들 손 위주라서 동양인들에게는 너무 컸음. 그 저기 서양 형님들 떡대 봐봐요 장난아님.

 

장르별 실적+주력 장르

# 글로벌 판매량 기준으로 장르별 실적 비교
genre_pivot = (video_df.query('Platform_Vendor in @console_three')
                .groupby(['Platform_Vendor', 'Genre'], observed=False)['Global_Sales']
                .sum()
                .unstack())

# 가독성을 위해 배경색 입히기 (주피터 노트북 환경)
genre_pivot.style.format("{:.3f}").background_gradient(cmap='coolwarm', axis=1)

마소는 슈터하고 액션, 닌텐도는 플랫폼과 액션, Misc(뭐임?), 스포츠, 롤플레잉, 소니는 액션이랑 스포츠. 이 장르들에서 많이 해먹었다.

 

실제로도 보면 세 콘솔에서 유명한 게임이 다 다른데, 닌텐도는 마리오+젤다+동숲+스플래툰+커비를 비롯한 퍼스트 파티와 포켓몬(퍼스트 파티는 아님) 등, 다양한 IP를 활용해서 다양한 게임을 내는데 이 게임들을 닌텐도 기기를 사야만 할 수 있다. 그러니까 이거 할 거면 우리 기기를 반드시 사라! 이거임. 그리고 다양한 IP를 활용해서 다양한 게임들을 내기때문에 주력이라고 할 수 있을 장르도 여러개다.

 

플스는 내가 안해봐서(플스 잡아본 적 없음) 구글링했는데, 플스의 주력 게임 중 하나가 파이널 판타지이다. 티파! 에어리스! 그거 맞음. 달을 보고 있었다가 파판 16 OST인가 그래요. 그 켄시가 부른거 함 들어보십쇼. 그 외에도 갓 오브 워나 마블 스파이더맨, 호라이즌 제로 던도 있고 동아리에서 선배들이 많이 했던 위닝도 있었다.

 

엑박은 가장 많이 떠올리시는게 헤일로, 기어스 오브 워인데 둘다 일단 총겜이고... 데드스페이스도 엑박에서 나오지 않았나? 그리고 포르자 시리즈도 있다. 포르자는 총겜은 아님.

 

시대, 그리고 게임

# 이제 그룹바이 기준이 연도로 바뀌게 된다. 단, 연도가 0으로 된 것은 빼고. (발매 취소된 겜이라... )
video_df_cp = video_df.copy()
video_df_cp.drop(video_df_cp[video_df_cp['Year'] == 0].index, inplace=True)
video_df_cp['Era'] = video_df_cp['Era'].cat.remove_unused_categories()

video_df_cp.groupby(['Era', 'Platform'], observed=False)['Name'].count().reset_index(name='Game_Count')

저 데이터 안에 연도가 NaN인 게임 중 하나가 발매 취소된 게임이다. 그래서 퍼블리셔는 있는데 발매년도가 없다.

 

platform_pivot = video_df_cp.pivot_table(index='Era', columns='Platform', values='Global_Sales', aggfunc='sum', observed=False)
platform_pivot

피벗테이블이 가로로 너무 길어서 이건 캡쳐 못했음. 그럼 닌텐도가 왜 북미에서 짱짱맨이 되었는지를 얘기해보자.

 

아타리 쇼크를 아십니까? 들어본 사람도 있을거고, 그 시대에 살았던 사람도 계실거고, 처음 듣는 사람도 있을텐데 닌텐도 이전에 아타리가 있었다. 근데 년도를 잘 보니까 80년대에 나왔다가 90년대부터 판매량이 0이네요? 아타리 쇼크가 83년부터 85년까지였거든…

 

아타리가 플랫폼을 만드는 회사라는 건 알겠어. 근데 아타리 쇼크는 뭐고, 닌텐도가 어떻게 그 자리를 차지한거지? 에 대한 얘기를 하려면 아타리 쇼크 얘기를 해야 한다. 엔씨 아시죠 엔씨? 그 리니지 만드는 회사. 걔네가 처음부터 그렇게 욕먹던 회사가 아니었고, 블소 초창기에는 진짜 갓겜 만드는 회사였어요. 근데 지금은 게임 낸다고 쇼케이스 나오면 다들 반응이 그래서 과금 모델은 어떤데? 어차피 리니지라이크 아냐? 이러잖아. 나도 엔씨게임은 진짜 안하지만 갓겜시절에는 블소 즐기고 그랬거든요.

 

그래서 송재경님을 만난다면 하나 꼭 물어보고 싶은 게 '개고기탕후루'라는 말을 듣고 어떤 심정이었는지임. 개고기탕후루가 멸칭입니다, 멸칭. 아마 택진이형은 최초로 개고기탕후루라는 말을 만들어낸 사람을 진짜 애타게 찾고싶을거임.

 

갑자기 엔씨 얘기가 왜 나옴? 얘네가 리니지 블소 다 갓겜이었는데 개고기탕후루 소리를 왜 들어요? 그죠. 게임이 그놈이 그놈인데 리니지라이크에 과금은 무슨 차 한대값을 박아야 게임 속에서 숨을 쉴 수 있잖아요. 아타리도 비슷한 이유로 망했다고 보시면 됩니다. 엔씨는 리니지라이크가 돈이 되니까 그것만 찍어냈다가 개고기탕후루 소리를 듣는거고, 아타리는 게임이 돈이 된다고 서드파티들이 겁나 찍어냈는데 그게 지금 엔씨게임이랑 비교하는것조차 실례일 정도로 진짜 쌉똥겜 투성이라 그렇게 된 거다. 엔씨 영업이익 떨어졌다고 가끔 기사 뜨죠? 아타리 쇼크때 아타리는 그냥 조낸 망했습니다.

 

이 때 미국 게임 시장에 처음으로 뛰어든 선구자가 닌텐도였다. 근데 그때 사람들이 하도 개똥겜들을 많이 봐서 게임을 무슨 악마의 똥같은 걸로 취급하는 걸 본 닌텐도가 저희는 게임기가 아니라 엔터테인먼트 시스템(Entertainment System)입니다~ 하고 들어가서 북미 시장을 먹은거다.

 

그리고 그 '엔터테인먼트 시스템'이 NES다.

 

그 뒤에 소니가 쓱 참전해서 플.엑 구도가 된거고

 

빌형은 왜 거기 낀거임 근데?

 

의 압축버전. 

 

플랫폼별 일짱은 누구?

벤더별 일짱

# 1. 각 플랫폼별 Global_Sales가 가장 높은 행의 인덱스 추출
idx = video_df.groupby('Platform')['Global_Sales'].idxmax()

# 2. 해당 인덱스의 데이터만 추출하여 정리
top_titles = video_df.loc[idx, ['Platform_Vendor', 'Platform', 'Name', 'NA_Sales', 'EU_Sales', 'JP_Sales', 'Other_Sales', 'Global_Sales']]

# 3. 제조사(Vendor)와 플랫폼별로 보기 좋게 정렬
top_titles = top_titles.sort_values(['Platform_Vendor', 'Global_Sales'], ascending=[True, False])

# 소수점 3자리 설정 및 출력
top_titles.style.format({
    'NA_Sales': '{:.3f}', 'EU_Sales': '{:.3f}', 
    'JP_Sales': '{:.3f}', 'Other_Sales': '{:.3f}', 'Global_Sales': '{:.3f}'
}).background_gradient(cmap='coolwarm', subset=['Global_Sales'])

우리집에 위는 없었지만 동방에는 있었다. 근데 이게 신박하긴 했음. 지금도 스위치 조이콘 빼서 휘두른다거나 그런거 있죠? 점프로프 챌린지도 그렇고. 그걸 나는 동아리방에서 위 리모콘으로 마리오카트랑 복싱 하면서 처음 써봤음. 근데 그런것치고 압도적인데…?

 

포켓몬 XY같은 경우 처음으로 3DS로 나온거고 모든 포켓몬이 3D화 됐고, 피카츄의 울음소리가 성우 울음소리로 바꼈는데 왜 롤백했냐 아오... 그래서 1세대~5세대 포켓몬은 버전별 이미지 찾아보면 도트에서 3D 됐잖아요. 라이츄 똥배때문에 도트뚱쥐됐는데 3D되면서 살 빠진거임. 동생놈이 염무왕의 존재를 알았다면 내 별명은 염무왕이었겠지... 아무튼. 그리고 포켓몬 XY, ORAS, SM, USUM에 있는 시스템 중에 포켓몬 아미에(7세대는 리플레)라는 게 있다. 내 포켓몬을 쮸담쮸담하고 하이파이브고 하고 뭐 그런거 있음. 그것때문에 잘 팔린게 아닐까 추정중이다.

 

플랫폼별 일짱

# 1. 각 플랫폼별 매출 1위 게임 추출
top_idx = video_df_cp.groupby('Platform')['Global_Sales'].idxmax()
platform_tops = video_df_cp.loc[top_idx, ['Platform', 'Name', 'NA_Sales', 'EU_Sales', 'JP_Sales', 'Other_Sales', 'Global_Sales']]

# 2. 보기 편하게 판매량 순으로 정렬 (상위 15개 기종)
platform_tops = platform_tops.sort_values('Global_Sales', ascending=False).head(15)

# 3. 소수점 3자리 조절 및 스타일링
platform_tops.style.format("{:.3f}", subset=['NA_Sales', 'EU_Sales', 'JP_Sales', 'Other_Sales', 'Global_Sales'])\
                    .background_gradient(cmap='coolwarm', subset=['Global_Sales'])\
                    .bar(subset=['NA_Sales', 'EU_Sales', 'JP_Sales'], color='#FFA07A')\
                    .bar(subset=['Other_Sales'], color='#FFD700')

포켓몬이 3위야 세상에...

 

# 시각화를 위해 게임 이름을 인덱스로 설정
plot_data = platform_tops.set_index('Name')[['NA_Sales', 'EU_Sales', 'JP_Sales', 'Other_Sales']]

# 누적 막대 그래프 그리기
plot_data.plot(kind='barh', stacked=True, figsize=(12, 8), colormap='coolwarm')
plt.title('Sales Breakdown by Region for Top Titles per Platform', fontsize=15)
plt.xlabel('Sales (Millions)')
plt.ylabel('Top Game Title')
plt.legend(title='Region', bbox_to_anchor=(1.05, 1), loc='upper left')
plt.show()

저는 wii를 안해봐서 쟤가 왜 잘 팔렸는지 모르겠습니다.

 

플랫폼, 그리고 시대별 일짱은?

# 1. Vendor와 Era별로 Global_Sales가 최대인 행의 인덱스를 추출
# observed=True를 써서 데이터가 없는 Unknown 시대는 제외합니다.
top_idx_era = video_df_cp.groupby(['Platform_Vendor', 'Era'], observed=True)['Global_Sales'].idxmax()

# 2. 해당 인덱스로 데이터프레임 생성
era_champions = video_df_cp.loc[top_idx_era, 
                                ['Platform_Vendor', 'Era', 'Platform', 'Name', 'NA_Sales', 'JP_Sales', 'Global_Sales']]

# 3. 가독성을 위해 정렬
era_champions = era_champions.sort_values(['Platform_Vendor', 'Era'])

# 4. 소수점 3자리와 스타일 적용
era_champions.style.format("{:.3f}", subset=['NA_Sales', 'JP_Sales', 'Global_Sales'])\
                    .background_gradient(cmap='coolwarm', subset=['Global_Sales'])

본인 참고로 키넥트도 안해봄. 집에 일단 콘솔 둘 데가 없습니다. ...팩맨이 혹시 우리가 아는 그 팩맨임?

 

에이, 원툴 아냐? 

# 1. 진영별 전체 매출 합계
vendor_total = video_df_cp.groupby('Platform_Vendor')['Global_Sales'].sum()

# 2. 진영별 상위 10개 게임의 매출 합계
top10_sum = (video_df_cp.sort_values('Global_Sales', ascending=False)
                .groupby('Platform_Vendor')
                .head(10)
                .groupby('Platform_Vendor')['Global_Sales'].sum())

# 3. 비중 계산 (단위: %)
dependency_df = pd.DataFrame({
    'Total_Sales': vendor_total,
    'Top10_Sales': top10_sum,
    'Dependency_Rate(%)': (top10_sum / vendor_total) * 100
}).sort_values('Dependency_Rate(%)', ascending=False)

dependency_df.style.format("{:.3f}")

플랫폼별 일짱이 전체 매출에 얼마나 기여했는지를 보자. 위스포츠가 잘나가긴 했지만, 그럼에도 10%정도다. 마소의 헤일로2나 플스의 다른 게임들도 마찬가지.

 

한짤요약

# 시각화를 위한 통합 대시보드 설정
fig, axes = plt.subplots(2, 2, figsize=(20, 15))
fig.suptitle('비디오 게임 콘솔 삼국지: 데이터로 본 반전의 역사', fontsize=25, fontweight='bold')

# 1. [좌상단] 시대별 플랫폼 제조사 매출 추이 (The History)
era_revenue = video_df_cp.groupby(['Era', 'Platform_Vendor'], observed=True)['Global_Sales'].sum().unstack().fillna(0)
era_revenue.plot(kind='area', stacked=True, ax=axes[0, 0], alpha=0.7, cmap='coolwarm')
axes[0, 0].set_title('① 시대별 진영 점유율: 아타리의 몰락과 닌텐도/소니의 부상', fontsize=15)
axes[0, 0].set_ylabel('Global Sales (Millions)')

# 2. [우상단] TOP 10 의존도 비교 (The Myth Buster)
sns.barplot(x=dependency_df.index, y='Dependency_Rate(%)', data=dependency_df, hue = dependency_df.index, ax=axes[0, 1], palette='coolwarm')
axes[0, 1].set_title('② "닌텐도는 원툴?" NO! 상위 10개 타이틀 매출 비중 비교', fontsize=15)
axes[0, 1].set_ylim(0, 110) # 3DO 등 소규모 벤더 제외하고 주요 3사 강조를 위해 조정 가능
for p in axes[0, 1].patches:
    axes[0, 1].annotate(f'{p.get_height():.1f}%', (p.get_x() + p.get_width() / 2., p.get_height()), 
                        ha='center', va='center', xytext=(0, 9), textcoords='offset points')

# 3. [좌하단] 주요 진영별 국가별 판매 비중 (Region Strategy)
vendor_region = video_df_cp.groupby('Platform_Vendor')[['NA_Sales', 'EU_Sales', 'JP_Sales']].sum()
vendor_region_pct = vendor_region.div(vendor_region.sum(axis=1), axis=0) * 100
vendor_region_pct.loc[['Nintendo', 'Sony', 'Microsoft']].plot(kind='barh', stacked=True, ax=axes[1, 0], colormap='coolwarm')
axes[1, 0].set_title('③ 진영별 국가별 공략지: 북미의 MS vs 일본의 닌텐도 vs 균형의 소니', fontsize=15)
axes[1, 0].set_xlabel('Sales Percentage (%)')

# 4. [우하단] 플랫폼별 일짱 게임의 위엄 (The Champions)
sns.barplot(x='Global_Sales', y='Name', data=platform_tops.head(10), hue='Global_Sales', ax=axes[1, 1], palette='coolwarm')
axes[1, 1].set_title('④ 역대 가장 강력했던 "일짱" 타이틀 TOP 10', fontsize=15)
axes[1, 1].set_xlabel('Global Sales (Millions)')

plt.tight_layout(rect=[0, 0.03, 1, 0.95])
plt.show()

1. 태초에 아타리가 있었지만 아타리 쇼크로 개같이 멸망했고, 그 자리를 닌텐도가 '엔터테인먼트 시스템'을 표방하면서 들어왔다. 그 다음에 소니가 들어와서 플.엑 양대산맥이 됐다가 삘받았는지  빌횽이 엑박을 내면서 플.엑.닌 삼국지가 된 것.

2. 위 스포츠의 판매량이 압도적인 건 인정. 하지만 닌텐도가 그걸로 원툴이었던 건 아니다.

3. 플.엑.닌은 각자의 특징을 살려서 삼국지 시장전을 하고 있다.

4. 닌텐도는 자사의 퍼스트파티들(마리오, 젤다, 동숲, 커비, 스플래툰)과 세컨트파티(포켓몬 등) 등의 IP를 내세운 독점작을 통한 이거 하려면 우리거 사세요~ 전략과 마리오 파티, 마리오 카트처럼 아이들도 즐길 수 있는 '엔터테인먼트'를 표방한 게임들을 만들었다.

5. 소니는 닌텐도보다 한 발 늦었지만, 어른이들을 위한 세련된 콘솔과 다양한 써드파티 게임들로 고객들을 끌어들였다.

6. 마소는 진입 시기가 제일 늦었던데다가 초기에 있었던 여러가지 이슈들로 인해 데이터상으로 플.엑.닌중에서 제일 판매량이 적고 일본 매출도 저조하지만, 포르자 시리즈와 헤일로, 기어스 오브 워 등의 총게임으로 북미 시장을 책임지고 있다.

'Coding > EDA' 카테고리의 다른 글

Post-COVID Video Games Worldwide (2021-2025)  (0) 2026.02.10
또 ChEMBL을 털어보았다  (0) 2026.01.28
캐글 EDA-마! 서퍼티파이! (2)  (0) 2026.01.20
캐글 EDA-마! 서퍼티파이!  (0) 2026.01.19
그냥 해보는 ChEMBL EDA  (0) 2026.01.15

댓글

홈으로 돌아가기

검색 결과

"search" 검색 결과입니다.