과거에 Rainbow Six Siege를 플레이하고 느낀점은 '신규 유저에게 진입장벽이 너무 높다' 였다.
꾸준한 업데이트를 통해 다양한 특수 능력을 가진 오퍼레이터나 외우기 벅찬 맵들이 추가됨에 따라 이 진입장벽은 더욱 더 높아진다고 느꼈다.
물론 몸으로 직접 부딪히며 게임을 수십~수백판 반복해서 오퍼레이터가 갖고 있는 능력들과 복잡한 맵들에 익숙해질 수는 있겠지만 그 전에 나가 떨어지는 뉴비들도 적잖이 많겠다고 생각했다.
수많은 선택지 중에서 어떤 오퍼레이터를, 그리고 어떤 무기를 들어야할지 고민하는 뉴비들에게 픽률과 승률 등을 기반으로 한 오퍼레이터 & 무장 추천이 가능하다면 리텐션을 조금 더 확보할 수 있지 않을까 생각하였다.
따라서 뉴비들을 위한 가이드에 활용할 수 있는 지표들을 몇가지 생각하여 분석해보았다.
- Rainbow Six Siege - S5 - Ranked Dataset 中 일부
- 약 4년 전의 데이터이며 해당 게임은 현재까지 업데이트가 지속적으로 이뤄지는 중이다.
- 따라서 분석을 진행하며 나오는 내용은 현재와 다를 수 있다.
- SQL
- Big Query
- Python
- Jupyter notebook
- Google Sheet
- 파이썬을 이용하여 간단한 데이터 전처리를 진행하였다.
csv 불러오기
r6s = pd.read_csv('./datadump_s5-000 copy.csv')
행, 열 확인하기
r6s.shape
(4000000, 31)
컬럼명 확인하기
r6s.columns
Index(['dateid', 'platform', 'gamemode', 'mapname', 'matchid', 'roundnumber', 'objectivelocation', 'winrole', 'endroundreason', 'roundduration', 'clearancelevel', 'skillrank', 'role', 'team', 'haswon', 'operator', 'nbkills', 'isdead', 'primaryweapon', 'primaryweapontype', 'primarysight', 'primarygrip', 'primaryunderbarrel', 'primarybarrel', 'secondaryweapon', 'secondaryweapontype', 'secondarysight', 'secondarygrip', 'secondaryunderbarrel', 'secondarybarrel', 'secondarygadget'], dtype='object')
결측치 확인하기
r6s.isnull().sum()
dateid 0 platform 0 gamemode 0 mapname 0 matchid 0 roundnumber 0 objectivelocation 0 winrole 0 endroundreason 0 roundduration 0 clearancelevel 0 skillrank 0 role 0 team 0 haswon 0 operator 0 nbkills 0 isdead 0 primaryweapon 0 primaryweapontype 0 primarysight 0 primarygrip 0 primaryunderbarrel 0 primarybarrel 0 secondaryweapon 0 secondaryweapontype 0 secondarysight 0 secondarygrip 0 secondaryunderbarrel 0 secondarybarrel 0 secondarygadget 0 dtype: int64
컬럼 삭제하기
- 불필요한 컬럼을 삭제해서 테이블의 크기를 줄였다.
delete = [ 'platform', 'roundduration', 'clearancelevel', 'skillrank', 'primaryweapontype', 'primarysight', 'primarygrip', 'primaryunderbarrel', 'primarybarrel', 'secondaryweapontype', 'secondarysight', 'secondarygrip', 'secondaryunderbarrel', 'secondarybarrel', 'secondarygadget', 'team'] r6s.drop(delete, inplace=True, axis=1)
날짜 확인하기
r6s['dateid'].unique()
array([20170212, 20170213, 20170216, 20170221])
고유값 수 확인하기
r6s.nunique()
dateid 4 gamemode 3 mapname 16 matchid 75157 roundnumber 9 objectivelocation 142 winrole 2 endroundreason 15 role 2 haswon 2 operator 35 nbkills 9 isdead 2 primaryweapon 46 secondaryweapon 16 dtype: int64
- 4,000,000 Row
- 31 Columns → 15 Columns (전처리 후)
- 2017-02-12
2017-02-13
2017-02-16
2017-02-21- 3 gamemode (HOSTAGE, BOMB, SECURE AREA)
- 16 map
- 35 operator (예비병력 제외 총 30명)
- 46 primary weapon
- 총 75,157번의 매치에 대한 개별 플레이어 데이터
(사용 오퍼레이터, 무장, 킬데스 등)
(매치당 최대 10 플레이어)
- R6:Siege는 공격팀과 수비팀(팀당 최대 5명)으로 나누어져 진행이 되는데,
각 팀에 유리한 맵이 존재하는지 승률을 통해 확인해보았다.WITH match as ( SELECT matchid, dateid, mapname, COUNT(DISTINCT CASE WHEN winrole = 'Attacker' THEN 1 ELSE NULL END) as atk_win, COUNT(DISTINCT CASE WHEN winrole = 'Defender' THEN 1 ELSE NULL END) as dfd_win, FROM `vaulted-cogency-295111.practice.r6s` GROUP BY matchid, dateid, mapname ORDER BY matchid, dateid ) SELECT mapname, ROUND(SUM(atk_win) / (SUM(atk_win) + SUM(dfd_win)) * 100.0, 2) AS atk_win, ROUND(SUM(dfd_win) / (SUM(atk_win) + SUM(dfd_win)) * 100.0, 2) AS dfd_win FROM match GROUP BY mapname ORDER BY dfd_win DESC ;
- 최대 승률이 50.16%, 최소가 49.84%로 큰 차이가 없다는 것을 알 수 있었다.
- 하지만 11:5 비율로 수비팀 승률이 높은 맵이 더 많다는 것도 알 수 있었다.
- R6:Siege는 게임 내에 인질, 폭탄 등의 오브젝트가 존재한다.
- 공격팀은 이 오브젝트를 탈취/무력화 하는 것이 목표이고,
- 수비팀은 이 오브젝트를 공격팀으로부터 지키는 것이 목표이다.
- 수비팀은 매 라운드마다 오브젝트의 위치를 팀 내 투표를 통해 결정하게 되는데
이 오브젝트의 위치에 따라 수비팀의 승률이 어떻게 달라지는지 알아보았다.- 맵이 총 16개이며 맵별로 선택 가능한 오브젝트의 위치는 10개 정도이다.
쿼리 결과가 160row로 너무 길기 때문에 맵별 승률 TOP & BOTTOM 1만 추려보았다.WITH match as ( SELECT matchid, dateid, mapname, objectivelocation, winrole, COUNT(*) AS num_player, COUNT(DISTINCT CASE WHEN winrole = 'Attacker' THEN 1 ELSE NULL END) as atk_win, COUNT(DISTINCT CASE WHEN winrole = 'Defender' THEN 1 ELSE NULL END) as dfd_win, FROM `vaulted-cogency-295111.practice.r6s` GROUP BY matchid, dateid, mapname, objectivelocation, winrole ORDER BY matchid, dateid ) SELECT mapname, objectivelocation, ROUND(SUM(atk_win) / (SUM(atk_win) + SUM(dfd_win)) * 100.0, 2) AS atk_win, ROUND(SUM(dfd_win) / (SUM(atk_win) + SUM(dfd_win)) * 100.0, 2) AS dfd_win, RANK() OVER(PARTITION BY mapname ORDER BY (SUM(dfd_win) / (SUM(atk_win) + SUM(dfd_win)) * 100.0) DESC) AS dfd_win_rank FROM match GROUP BY mapname, objectivelocation ORDER BY mapname, dfd_win_rank ;
- 승률이 크게 차이나지 않는 곳도 있지만, YACHT와 BANK 등 승률이 60%를 넘는 곳도 있었다.
- 특히 CLUB_HOUSE 맵의 경우 수비팀 승률이 오브젝트 위치에 따라 최대 60.01%, 최소 37.69%로 위치별 승률이 약 23%p 정도 차이가 났다.
- 따라서 오브젝트 위치가 수비팀의 승패에 어느 정도 영향이 있다는 것을 알 수 있었다.
- R6:Seige는 매 라운드 플레이어가 플레이할 캐릭터를 고르게 되는데, 이 캐릭터를 오퍼레이터라고 부른다.
- 오퍼레이터들은 각자 특수능력을 보유하고 있고 공격팀/수비팀 각각 고를 수 있는 오퍼레이터가 구분되어 있다.
- 플레이어들이 각 오퍼레이터를 선택한 비율을 알아보았다.
- 특수능력이 없는 예비병력을 제외하고 공격/수비 각 15명씩 총 30명의 오퍼레이터만 확인해 보았다.
SELECT role, operator, COUNT(*) AS pick_count, ROUND((COUNT(*) / SUM(COUNT(*)) OVER(PARTITION BY role)) * 100.0, 2) AS pick_rate, RANK() OVER(PARTITION BY role ORDER BY COUNT(*) DESC) AS pick_rank FROM `vaulted-cogency-295111.practice.r6s` WHERE operator NOT LIKE ('%RESERVE') GROUP BY role, operator ORDER BY role, pick_rank ;
- 상위권과 하위권의 픽률 격차가 어느 정도 있는 것으로 나타난다.
- 특히 Blitz, Echo, Tachanka는 최하위권이며 바로 앞 순위와 격차가 큰 것을 알 수 있다.
- 바로 다음에서 진행할 '오퍼레이터별 승률 & 킬데스' 에서 성능에 문제가 있는지 알아보았다.
- 오퍼레이터별 승률과 킬데스 비율(킬 수 / 데스 수)을 확인하여 직전에 분석한 플레이어들의 픽률이 근거가 있는 선택이었는지 알아보았다.
- 특수능력이 없는 예비병력은 제외하였다.
- 승률 순위(win_rate_rank)와 킬데스 순위(kill_death_rank)를 종합하여 성적이 높은 순서로 정렬하였다.
SELECT role, operator, COUNT(*) AS match_count, SUM(CASE WHEN haswon = 1 THEN 1 ELSE NULL END) AS win, SUM(CASE WHEN haswon = 0 THEN 1 ELSE NULL END) AS lose, ROUND((SUM(CASE WHEN haswon = 1 THEN 1 ELSE NULL END) / COUNT(*)) * 100.0, 2) AS win_rate, ROUND(SUM(nbkills) / SUM(isdead), 2) AS kill_death_ratio, RANK() OVER(PARTITION BY role ORDER BY ((SUM(CASE WHEN haswon = 1 THEN 1 ELSE NULL END) / COUNT(*)) * 100.0) DESC) AS win_rate_rank, RANK() OVER(PARTITION BY role ORDER BY (SUM(nbkills) / SUM(isdead)) DESC) AS kill_death_rank FROM `vaulted-cogency-295111.practice.r6s` WHERE operator NOT LIKE ('%RESERVE') GROUP BY role, operator ORDER BY role, (win_rate_rank + kill_death_rank) / 2 ;
- 직전에 분석한 픽률과 비교해보았을 때 픽률과 성적 순위가 비슷하게 나타났다.
- 수치상으로 나타나는 승률과 킬데스 비율 차이를 유저들 또한 플레이를 통해 체감하여 픽률에 영향을 주었다는 점이 흥미로웠다.
- 또한 픽률에서 최하위권이며 격차가 컸던 Blitz, Echo, Tachanka 중 Echo를 제외한 Blitz와 Tachanka는 승률과 킬데스 역시 최하위권에 속하였다.
- 오퍼레이터 성능 조절 혹은 리워크를 통한 밸런스 조절이 필요하다고 생각한다.
- 위에서 오퍼레이터별 승률과 킬데스를 알아보았는데, 이번에는 맵에 따라서 승률과 킬데스가 어떻게 변하는지 알아보았다.
- 예비병력은 제외하고 맵, 팀별 TOP 1만 추려보았다.
- 승률 순위(win_rate_rank)와 킬데스 순위(kill_death_rank)를 종합하여 성적이 높은 순서로 정렬하였다.
SELECT mapname, role, operator, COUNT(*) AS match_count, SUM(CASE WHEN haswon = 1 THEN 1 ELSE NULL END) AS win, SUM(CASE WHEN haswon = 0 THEN 1 ELSE NULL END) AS lose, ROUND((SUM(CASE WHEN haswon = 1 THEN 1 ELSE NULL END) / COUNT(*)) * 100.0, 2) AS win_rate, ROUND(SUM(nbkills) / SUM(isdead), 2) AS kill_death_ratio, RANK() OVER(PARTITION BY mapname, role ORDER BY ((SUM(CASE WHEN haswon = 1 THEN 1 ELSE NULL END) / COUNT(*)) * 100.0) DESC) AS win_rate_rank, RANK() OVER(PARTITION BY mapname, role ORDER BY (SUM(nbkills) / SUM(isdead)) DESC) AS kill_death_rank FROM `vaulted-cogency-295111.practice.r6s` WHERE operator NOT LIKE ('%RESERVE') GROUP BY operator, role, mapname order by mapname, role, (win_rate_rank + kill_death_rank) / 2 ;
- 몇개의 오퍼레이터 빼고는 전부 같은 이름이 반복되어 나타나지만, 그래도 꽤 다양한 오퍼레이터들이 활약하고 있음을 알 수 있었다.
- 공격팀 오퍼레이터 Glaz와 Fuze의 경우 각각 Plane, Kanal 맵에서 승률과 킬데스 모두 1위라는 기록을 보여주었다.
- 하지만 해당 맵 한정이고, 또한 이전에 분석한 종합 픽률과 성적 모두 TOP 3에 들지 못했다는 부분이 흥미로웠다.
SELECT
primaryweapon,
COUNT(*) AS match_count,
SUM(CASE WHEN haswon = 1 THEN 1 ELSE NULL END) AS win,
SUM(CASE WHEN haswon = 0 THEN 1 ELSE NULL END) AS lose,
ROUND((SUM(CASE WHEN haswon = 1 THEN 1 ELSE NULL END) / COUNT(*)) * 100.0, 2) AS win_rate,
SUM(nbkills) AS kill,
SUM(isdead) AS death,
ROUND(SUM(nbkills) / SUM(isdead), 2) AS kill_death_ratio,
RANK() OVER(ORDER BY ((SUM(CASE WHEN haswon = 1 THEN 1 ELSE NULL END) / COUNT(*)) * 100.0) DESC) AS win_rate_rank,
RANK() OVER(ORDER BY (SUM(nbkills) / SUM(isdead)) DESC) AS kill_death_rank
FROM
`vaulted-cogency-295111.practice.r6s`
GROUP BY
primaryweapon
ORDER BY
(win_rate_rank + kill_death_rank) / 2
;
- 위에서 말했듯이 오퍼레이터마다 고를 수 있는 주무기가 정해져있다.
- 오퍼레이터별로 구분하여 주무기의 성적을 비교해보았다.
- 특수능력이 없는 예비병력은 제외하였다.
- 승률 순위(win_rate_rank)와 킬데스 순위(kill_death_rank)를 종합하여 성적이 높은 순서로 정렬하였다.
SELECT operator, primaryweapon, COUNT(*) AS match_count, SUM(CASE WHEN haswon = 1 THEN 1 ELSE NULL END) AS win, SUM(CASE WHEN haswon = 0 THEN 1 ELSE NULL END) AS lose, ROUND((SUM(CASE WHEN haswon = 1 THEN 1 ELSE NULL END) / COUNT(*)) * 100.0, 2) AS win_rate, SUM(nbkills) AS kill, SUM(isdead) AS death, ROUND(SUM(nbkills) / SUM(isdead), 2) AS kill_death_ratio, RANK() OVER(PARTITION BY operator ORDER BY ((SUM(CASE WHEN haswon = 1 THEN 1 ELSE NULL END) / COUNT(*)) * 100.0) DESC) AS win_rate_rank, RANK() OVER(PARTITION BY operator ORDER BY (SUM(nbkills) / SUM(isdead)) DESC) AS kill_death_rank FROM `vaulted-cogency-295111.practice.r6s` WHERE operator NOT LIKE ('%RESERVE') GROUP BY operator, primaryweapon order by operator, (win_rate_rank + kill_death_rank) / 2 ;
- 오퍼레이터마다 고를 수 있는 주무기가 2~3개 존재하는 것을 알 수 있었다.
- 여러 오퍼레이터가 사용 가능한 주무기가 있는 반면에 특정 오퍼레이터만 사용할 수 있는 주무기도 존재했다.
- 무기 종합 성적에서 1위를 차지한 F2는 오퍼레이터 종합 성적에서 공동 1위를 차지한 Twitch의 고유 무기인 것을 알 수 있었다.
- R6:Siege의 한 판은 보통 5라운드로 진행이 된다.
- 라운드 종료, 즉 라운드의 승리팀이 정해지고 해당 라운드가 종료되는 사유로는 어떤 것이 있고 각각의 빈도가 어떻게 되는지 알아보았다.
SELECT endroundreason, COUNT(*) AS match_count, ROUND((COUNT(*) / SUM(COUNT(*)) OVER(ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)) * 100.0, 2) AS ratio FROM `vaulted-cogency-295111.practice.r6s` GROUP BY endroundreason ORDER BY ratio DESC ;
- 수비팀/공격팀 전멸이 85.5%의 비율을 차지하는 것을 알 수 있었다.
- 나머지 15%를 구성하는 사유는 오브젝트 탈취/보호/파괴 등 오브젝트 관련 요소가 거의 차지하고 있으며 상대팀 전원이 게임을 나간 경우, 항복한 경우 등의 사유도 적은 비율로 존재했다.
- 팀의 전멸이 라운드 종료 사유 85.5%를 차지하는 것으로 보았을 때 킬 & 데스가 승패에 미치는 영향이 클 것으로 예상이 된다.
- 이를 확인해보기 위해 킬 & 데스와 승패 사이의 상관계수를 확인해보았다.
WITH killdeath AS ( SELECT matchid, roundnumber, role, haswon, SUM(nbkills) AS kill, SUM(isdead) AS death, FROM `vaulted-cogency-295111.practice.r6s` GROUP BY matchid, roundnumber, role, haswon ORDER BY matchid, roundnumber, role ) SELECT corr(kill, haswon) AS kill_corr, corr(death, haswon) AS death_corr FROM killdeath ;
- 킬의 경우 약 0.715로 강한 양적 선형관계를 나타낸다.
- 데스의 경우 약 -0.743으로 강한 음적 선형관계를 나타낸다.
- 예상한대로 킬데스가 승패에 큰 영향을 미친다는 것을 알 수 있었다.
- 경기를 오래 끌수록, 혹은 빨리 끝낼수록 유불리한 팀이 있는지 궁금했다.
- 아래의 단계를 통해 라운드가 지속됨에 따라 공격팀/수비팀의 승률이 어떻게 달라지는지 확인해보았다.
1. 지속시간 평균, 최대, 최소값
- 비정상 값이 존재하는지 확인하기 위해 라운드 지속시간의 평균, 최대, 최소값을 구하였다.
SELECT AVG(roundduration) AS avg_round_duration, MAX(roundduration) AS max_round_duration, MIN(roundduration) AS min_round_duration FROM `vaulted-cogency-295111.practice.r6s` ;
- 평균 지속시간 : 186.6471449999994
- 최대 지속시간 : 23188
- 최소 지속시간 : 6
- 최대 & 최소 지속시간이 비정상적인 값으로 예상된다.
2. 시간대별 매치수
- 매치수가 몰려있는 구간을 파악하고 비정상 값을 걸러내기 위해 시간대별로 매치수를 확인하였다.
- 3,000 초과값은 우선적으로 제외하고 확인하였다.
WITH bucket AS ( SELECT lower, upper FROM UNNEST(GENERATE_ARRAY(0, 2900, 100)) AS lower, UNNEST(GENERATE_ARRAY(100, 3000, 100)) AS upper WHERE lower + 100 = upper ) SELECT winrole, lower, upper, COUNT(*) AS match_count, ROUND((SUM(CASE WHEN haswon = 1 THEN 1 ELSE 0 END) / COUNT(*)) * 100.0, 2) AS win_rate FROM `vaulted-cogency-295111.practice.r6s` as t INNER JOIN bucket ON t.roundduration > lower AND t.roundduration <= upper GROUP BY winrole, lower, upper ORDER BY winrole, lower ;
- 대부분의 값이 300 밑에 위치한 점, 라운드당 기본으로 주어지는 시간이 3분 45초인 점 등을 근거로 정상 범주를 0~240으로 정하고 분석을 진행하도록 하였다.
3. 시간대별 승률
- 0~240초를 10초 단위로 끊어서 팀별 승률을 알아보았다.
WITH bucket AS ( SELECT lower, upper FROM UNNEST(GENERATE_ARRAY(0, 230, 10)) AS lower, UNNEST(GENERATE_ARRAY(10, 240, 10)) AS upper WHERE lower + 10 = upper ), match as ( SELECT DISTINCT matchid, roundnumber, roundduration, winrole FROM `vaulted-cogency-295111.practice.r6s` ) SELECT lower, upper, COUNT(*) AS match_count, ROUND((SUM(CASE WHEN winrole = 'Attacker' THEN 1 ELSE 0 END) / COUNT(*)) * 100.0, 2) AS atk_win_rate, ROUND((SUM(CASE WHEN winrole = 'Defender' THEN 1 ELSE 0 END) / COUNT(*)) * 100.0, 2) AS dfd_win_rate FROM match INNER JOIN bucket ON roundduration > lower AND roundduration <= upper GROUP BY lower, upper ORDER BY lower ;
- 시작 초반(0~100)은 수비팀의 승률이 높다.
- 중반 이후(100~) 부터는 수비팀 승률이 점차적으로 떨어지는 것을 볼 수 있다.
- 200초를 기점으로 공격팀의 승률이 수비팀을 앞지르게 된다.
- 라운드 후반으로 갈수록 공격팀이 오브젝트에 접근할 가능성이 높아지기에 이런 양상을 보인다고 추측된다.
맵별로 공격팀/수비팀의 승률 차이는 거의 없지만 수비팀 승률이 높은 맵이 더 많다.
오브젝트 위치에 따라 수비팀 승률이 37~60%를 오가는 것으로 보았을 때 오브젝트 위치가 수비팀 승률에 영향이 미친다고 볼 수 있다.
오퍼레이터의 승률과 킬데스 비율이 유저들의 픽률에도 영향을 미친다.
특정 맵에서 성능이 뛰어난 오퍼레이터도 존재한다.(Glaz, Fuze)
하지만 대부분 몇몇 오퍼레이터가 상위권을 독차지하는 것으로 보인다.(Jackal, Jager 등)
신규 유저들에게 오퍼레이터와 총기를 추천하는 것도 좋지만 오퍼레이터들의 밸런스를 맞춰 픽 밸런스를 잡는 것이 가장 좋은 방법이라 생각된다.
오퍼레이터 리워크, 총기 밸런스 조절을 통해 오퍼레이터의 성능을 조절하는 방법도 괜찮다고 생각한다.
팀 전멸이 라운드 종료 사유의 85.5%를 차지하고 있다.
게임 초반은 수비팀, 게임 후반은 공격팀의 승률이 높다.