[OPGG] 라이엇 API 사용하기
Updated:
1. 내전 게임 불러오기
import pandas as pd
import numpy as np
import requests
import matplotlib as plt
# Riot Developer Portal에서 받은 API KEY입니다.
# 해당 값을 포함한 모든 종류의 KEY는 코드에 직접적으로 노출되지 않도록 하는 것이 좋습니다.
api_key = 'RGAPI-0c612bd4-12a0-4358-8d6b-9ea0cd92b1cf'
# 방금 진행한 내전의 gameId값입니다. 클라이언트 대전기록에서 확인할 수 있습니다.
gameid = 5382324388
requesturl = "https://kr.api.riotgames.com/lol/match/v4/matches/"+str(gameid)+"?api_key="+api_key
r = requests.get(requesturl)
-
라이엇 개발자 홈페이지에서 API 탭에 가면 여러 자료를 불러올 수 있다.
-
이번엔 그 중에서 강의 중 내전한 자료를 불러올 것이다.
-
gameid는 롤 대전기록 검색시 URL에서 확인 가능하다.
-
API KEY는 24시간 정도 유지되며 그 이후 사용시 재발급하여 사용하면 된다.
# 불러온 데이터 확인
# teamid 100: blue, 200: red
r.json().keys()
dict_keys(['gameId', 'platformId', 'gameCreation', 'gameDuration', 'queueId', 'mapId', 'seasonId', 'gameVersion', 'gameMode', 'gameType', 'teams', 'participants', 'participantIdentities'])
-
불러온 데이터는 json 형식의 파일로 이루어져 있다.
-
각 key별로 어떤 자료가 있는지는 홈페이지에 자세한 설명이 있다.
# 불러온 데이터 중 소환사1의 데이터 확인
# r.json()['participants'][0]
- participants에는 플레이한 소환사의 정보가 담겨있다.
# DataFrame으로 변환해서 확인
pd.DataFrame(r.json()['participants'])
participantId | teamId | championId | spell1Id | spell2Id | stats | timeline | |
---|---|---|---|---|---|---|---|
0 | 1 | 100 | 222 | 7 | 4 | {'participantId': 1, 'win': False, 'item0': 10... | {'participantId': 1, 'creepsPerMinDeltas': {'1... |
1 | 2 | 100 | 234 | 4 | 11 | {'participantId': 2, 'win': False, 'item0': 31... | {'participantId': 2, 'creepsPerMinDeltas': {'1... |
2 | 3 | 100 | 143 | 4 | 14 | {'participantId': 3, 'win': False, 'item0': 66... | {'participantId': 3, 'creepsPerMinDeltas': {'1... |
3 | 4 | 100 | 34 | 12 | 4 | {'participantId': 4, 'win': False, 'item0': 30... | {'participantId': 4, 'creepsPerMinDeltas': {'1... |
4 | 5 | 100 | 58 | 4 | 14 | {'participantId': 5, 'win': False, 'item0': 66... | {'participantId': 5, 'creepsPerMinDeltas': {'1... |
5 | 6 | 200 | 48 | 12 | 4 | {'participantId': 6, 'win': True, 'item0': 304... | {'participantId': 6, 'creepsPerMinDeltas': {'1... |
6 | 7 | 200 | 84 | 14 | 4 | {'participantId': 7, 'win': True, 'item0': 105... | {'participantId': 7, 'creepsPerMinDeltas': {'1... |
7 | 8 | 200 | 43 | 14 | 4 | {'participantId': 8, 'win': True, 'item0': 385... | {'participantId': 8, 'creepsPerMinDeltas': {'1... |
8 | 9 | 200 | 203 | 11 | 4 | {'participantId': 9, 'win': True, 'item0': 313... | {'participantId': 9, 'creepsPerMinDeltas': {'1... |
9 | 10 | 200 | 498 | 7 | 4 | {'participantId': 10, 'win': True, 'item0': 10... | {'participantId': 10, 'creepsPerMinDeltas': {'... |
-
이를 데이터프레임으로 바꿔보면 앞서 지정한 특정 게임의 플레이어 10명에 대한 정보가 담겨있다.
-
다만 stats와 timeline 등은 nested되어 있다.
# nested된 부분 unnest해서 DataFrame으로 변환
df = pd.json_normalize(r.json()['participants'])
df.head()
participantId | teamId | championId | spell1Id | spell2Id | stats.participantId | stats.win | stats.item0 | stats.item1 | stats.item2 | ... | timeline.csDiffPerMinDeltas.10-20 | timeline.csDiffPerMinDeltas.0-10 | timeline.xpDiffPerMinDeltas.10-20 | timeline.xpDiffPerMinDeltas.0-10 | timeline.damageTakenPerMinDeltas.10-20 | timeline.damageTakenPerMinDeltas.0-10 | timeline.damageTakenDiffPerMinDeltas.10-20 | timeline.damageTakenDiffPerMinDeltas.0-10 | timeline.role | timeline.lane | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 100 | 222 | 7 | 4 | 1 | False | 1055 | 6671 | 3094 | ... | -1.1 | -0.65 | 36.35 | -24.55 | 638.7 | 252.8 | 64.95 | -4.7 | DUO_CARRY | BOTTOM |
1 | 2 | 100 | 234 | 4 | 11 | 2 | False | 3153 | 2031 | 3047 | ... | -0.9 | 0.20 | -77.30 | -97.40 | 1354.3 | 892.3 | 294.40 | 206.7 | NONE | JUNGLE |
2 | 3 | 100 | 143 | 4 | 14 | 3 | False | 6653 | 2421 | 3853 | ... | -1.1 | -0.65 | 36.35 | -24.55 | 482.4 | 224.7 | 64.95 | -4.7 | DUO_SUPPORT | BOTTOM |
3 | 4 | 100 | 34 | 12 | 4 | 4 | False | 3040 | 6653 | 0 | ... | 0.6 | 0.30 | 36.60 | -52.30 | 546.4 | 127.0 | 43.10 | -189.6 | SOLO | MIDDLE |
4 | 5 | 100 | 58 | 4 | 14 | 5 | False | 6630 | 2031 | 3075 | ... | -1.9 | -1.00 | -99.20 | 4.30 | 1157.8 | 683.7 | 18.90 | 103.7 | SOLO | TOP |
5 rows × 126 columns
pd.json_normalize()
를 사용하면 다음과 같이 원하는 형태로 생성 가능하다.
# 확인할 변수
COLUMNS = ["participantId", "teamId", "championId", "spell1Id", "spell2Id", "stats.win",
"stats.item0","stats.item1","stats.item2","stats.item3","stats.item4","stats.item5","stats.item6",
"stats.kills","stats.deaths","stats.assists","stats.totalDamageDealt","stats.totalDamageTaken",
"stats.goldEarned"]
# 확인할 변수만 가져와서 새로운 DataFrame에 저장
df2 = df[COLUMNS]
# Column 이름에 불필요한 'stats.'가 붙은 걸 삭제
df2.columns = df2.columns.str.replace('stats.', '', regex = True)
# 최종 추출 형태 확인
df2
participantId | teamId | championId | spell1Id | spell2Id | win | item0 | item1 | item2 | item3 | item4 | item5 | item6 | kills | deaths | assists | totalDamageDealt | totalDamageTaken | goldEarned | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 100 | 222 | 7 | 4 | False | 1055 | 6671 | 3094 | 3006 | 1038 | 1037 | 3363 | 7 | 6 | 8 | 85575 | 16660 | 9877 |
1 | 2 | 100 | 234 | 4 | 11 | False | 3153 | 2031 | 3047 | 0 | 0 | 6632 | 3364 | 6 | 9 | 10 | 84491 | 32960 | 9053 |
2 | 3 | 100 | 143 | 4 | 14 | False | 6653 | 2421 | 3853 | 3020 | 3191 | 1028 | 3364 | 3 | 6 | 11 | 37787 | 12358 | 7565 |
3 | 4 | 100 | 34 | 12 | 4 | False | 3040 | 6653 | 0 | 0 | 3020 | 0 | 3364 | 4 | 5 | 4 | 101048 | 14466 | 8237 |
4 | 5 | 100 | 58 | 4 | 14 | False | 6630 | 2031 | 3075 | 3047 | 1054 | 0 | 3364 | 5 | 7 | 2 | 70397 | 29663 | 8345 |
5 | 6 | 200 | 48 | 12 | 4 | True | 3047 | 1054 | 6632 | 3051 | 3742 | 3076 | 3340 | 3 | 5 | 11 | 107619 | 27460 | 10940 |
6 | 7 | 200 | 84 | 14 | 4 | True | 1054 | 3020 | 3157 | 1052 | 4633 | 0 | 3340 | 2 | 2 | 5 | 64034 | 13449 | 8417 |
7 | 8 | 200 | 43 | 14 | 4 | True | 3853 | 2065 | 2055 | 3011 | 3158 | 0 | 3364 | 0 | 4 | 18 | 22255 | 9783 | 7729 |
8 | 9 | 200 | 203 | 11 | 4 | True | 3139 | 3026 | 3006 | 6672 | 6676 | 3094 | 3364 | 23 | 7 | 7 | 200929 | 24914 | 18384 |
9 | 10 | 200 | 498 | 7 | 4 | True | 1055 | 6671 | 3508 | 1038 | 0 | 3006 | 3363 | 5 | 7 | 7 | 116952 | 13582 | 10475 |
- 각 플레이어의 팀, 선택한 챔피언, 스펠, 승리 여부 등 일부 정보만 불러왔다.
# KDA = (K + A) / D
# GPM = goldEarned / (gameDuration_In_Munite)
# DPM = damageDealt / (gameDuration_In_Munite)
# DTPM = damageTaken / (gameDuration_In_Munite)
df3 = df2.assign(KDA=lambda x: (x['kills']+x['assists'])/x['deaths'])
df3['GPM'] = df3['goldEarned'] / r.json()['gameDuration'] * 60 # 분 단위
df3['DPM'] = df3['totalDamageDealt'] / r.json()['gameDuration'] * 60
df3['DTPM'] = df3['totalDamageTaken'] / r.json()['gameDuration'] * 60
-
KDA, GPM 등 개인 지표를 추가하였다.
-
KDA의 경우 Death가 0인 경우를 고려해서 짜도 될 것이다.
df3
participantId | teamId | championId | spell1Id | spell2Id | win | item0 | item1 | item2 | item3 | ... | kills | deaths | assists | totalDamageDealt | totalDamageTaken | goldEarned | KDA | GPM | DPM | DTPM | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 100 | 222 | 7 | 4 | False | 1055 | 6671 | 3094 | 3006 | ... | 7 | 6 | 8 | 85575 | 16660 | 9877 | 2.500000 | 368.086957 | 3189.130435 | 620.869565 |
1 | 2 | 100 | 234 | 4 | 11 | False | 3153 | 2031 | 3047 | 0 | ... | 6 | 9 | 10 | 84491 | 32960 | 9053 | 1.777778 | 337.378882 | 3148.732919 | 1228.322981 |
2 | 3 | 100 | 143 | 4 | 14 | False | 6653 | 2421 | 3853 | 3020 | ... | 3 | 6 | 11 | 37787 | 12358 | 7565 | 2.333333 | 281.925466 | 1408.211180 | 460.546584 |
3 | 4 | 100 | 34 | 12 | 4 | False | 3040 | 6653 | 0 | 0 | ... | 4 | 5 | 4 | 101048 | 14466 | 8237 | 1.600000 | 306.968944 | 3765.763975 | 539.105590 |
4 | 5 | 100 | 58 | 4 | 14 | False | 6630 | 2031 | 3075 | 3047 | ... | 5 | 7 | 2 | 70397 | 29663 | 8345 | 1.000000 | 310.993789 | 2623.490683 | 1105.453416 |
5 | 6 | 200 | 48 | 12 | 4 | True | 3047 | 1054 | 6632 | 3051 | ... | 3 | 5 | 11 | 107619 | 27460 | 10940 | 2.800000 | 407.701863 | 4010.645963 | 1023.354037 |
6 | 7 | 200 | 84 | 14 | 4 | True | 1054 | 3020 | 3157 | 1052 | ... | 2 | 2 | 5 | 64034 | 13449 | 8417 | 3.500000 | 313.677019 | 2386.360248 | 501.204969 |
7 | 8 | 200 | 43 | 14 | 4 | True | 3853 | 2065 | 2055 | 3011 | ... | 0 | 4 | 18 | 22255 | 9783 | 7729 | 4.500000 | 288.037267 | 829.378882 | 364.583851 |
8 | 9 | 200 | 203 | 11 | 4 | True | 3139 | 3026 | 3006 | 6672 | ... | 23 | 7 | 7 | 200929 | 24914 | 18384 | 4.285714 | 685.118012 | 7488.037267 | 928.472050 |
9 | 10 | 200 | 498 | 7 | 4 | True | 1055 | 6671 | 3508 | 1038 | ... | 5 | 7 | 7 | 116952 | 13582 | 10475 | 1.714286 | 390.372671 | 4358.459627 | 506.161491 |
10 rows × 23 columns
# 숫자로 된 각종 Key값에 대한 Value 가져오기
champion_constant = requests.get("http://ddragon.leagueoflegends.com/cdn/11.15.1/data/ko_KR/champion.json")
spell_constant = requests.get("http://ddragon.leagueoflegends.com/cdn/11.15.1/data/ko_KR/summoner.json")
item_constant = requests.get("http://ddragon.leagueoflegends.com/cdn/11.15.1/data/ko_KR/item.json")
-
챔피언, 스펠, 아이템에 대한 json 파일을 불러왔다.
-
이 역시 홈페이지에서 해당 URL을 확인 가능하다.
-
수업 당시 기준 11.15.1 버전 URL이나 업데이트 된다면 이를 바꿔주면 된다.
# champion_constant.json()
# Json 파일을 DataFrame으로 변환
champion_df = pd.DataFrame(champion_constant.json()['data']).T[['key','name']]
spell_df = pd.DataFrame(spell_constant.json()['data']).T[['key','name']]
item_df = pd.DataFrame(item_constant.json()['data']).T['name'].rename_axis("key").reset_index()
# 변수형 문자 -> 숫자
champion_df['key'] = pd.to_numeric(champion_df['key'])
spell_df['key'] = pd.to_numeric(spell_df['key'])
item_df['key'] = pd.to_numeric(item_df['key'])
- 이번에도 데이터 프레임 형태로 바꿔주되 각 파일의 컬럼이 매우 많아 일부만 사용한다.
# 매칭되는 곳으로 내용 추가하여 새로운 DataFrame으로 저장
df4 = pd.merge(df3,champion_df,how = 'left', left_on = 'championId', right_on = 'key')
# DataFrame 확인
df4
participantId | teamId | championId | spell1Id | spell2Id | win | item0 | item1 | item2 | item3 | ... | assists | totalDamageDealt | totalDamageTaken | goldEarned | KDA | GPM | DPM | DTPM | key | name | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 100 | 222 | 7 | 4 | False | 1055 | 6671 | 3094 | 3006 | ... | 8 | 85575 | 16660 | 9877 | 2.500000 | 368.086957 | 3189.130435 | 620.869565 | 222 | 징크스 |
1 | 2 | 100 | 234 | 4 | 11 | False | 3153 | 2031 | 3047 | 0 | ... | 10 | 84491 | 32960 | 9053 | 1.777778 | 337.378882 | 3148.732919 | 1228.322981 | 234 | 비에고 |
2 | 3 | 100 | 143 | 4 | 14 | False | 6653 | 2421 | 3853 | 3020 | ... | 11 | 37787 | 12358 | 7565 | 2.333333 | 281.925466 | 1408.211180 | 460.546584 | 143 | 자이라 |
3 | 4 | 100 | 34 | 12 | 4 | False | 3040 | 6653 | 0 | 0 | ... | 4 | 101048 | 14466 | 8237 | 1.600000 | 306.968944 | 3765.763975 | 539.105590 | 34 | 애니비아 |
4 | 5 | 100 | 58 | 4 | 14 | False | 6630 | 2031 | 3075 | 3047 | ... | 2 | 70397 | 29663 | 8345 | 1.000000 | 310.993789 | 2623.490683 | 1105.453416 | 58 | 레넥톤 |
5 | 6 | 200 | 48 | 12 | 4 | True | 3047 | 1054 | 6632 | 3051 | ... | 11 | 107619 | 27460 | 10940 | 2.800000 | 407.701863 | 4010.645963 | 1023.354037 | 48 | 트런들 |
6 | 7 | 200 | 84 | 14 | 4 | True | 1054 | 3020 | 3157 | 1052 | ... | 5 | 64034 | 13449 | 8417 | 3.500000 | 313.677019 | 2386.360248 | 501.204969 | 84 | 아칼리 |
7 | 8 | 200 | 43 | 14 | 4 | True | 3853 | 2065 | 2055 | 3011 | ... | 18 | 22255 | 9783 | 7729 | 4.500000 | 288.037267 | 829.378882 | 364.583851 | 43 | 카르마 |
8 | 9 | 200 | 203 | 11 | 4 | True | 3139 | 3026 | 3006 | 6672 | ... | 7 | 200929 | 24914 | 18384 | 4.285714 | 685.118012 | 7488.037267 | 928.472050 | 203 | 킨드레드 |
9 | 10 | 200 | 498 | 7 | 4 | True | 1055 | 6671 | 3508 | 1038 | ... | 7 | 116952 | 13582 | 10475 | 1.714286 | 390.372671 | 4358.459627 | 506.161491 | 498 | 자야 |
10 rows × 25 columns
- 챔피언 id를 기준으로 각 id가 어떤 챔피언인지 알 수 있게 merge한 결과이다.
# 중복되는 값 삭제
df4 = df4.rename(columns={'name': 'Champion'}).drop(['championId','key'],axis = 1)
df4 = pd.merge(df4,spell_df,how = 'left', left_on = 'spell1Id', right_on = 'key')
df4 = df4.rename(columns={'name': 'D'}).drop(['spell1Id','key'],axis = 1)
df4 = pd.merge(df4,spell_df,how = 'left', left_on = 'spell2Id', right_on = 'key')
df4 = df4.rename(columns={'name': 'F'}).drop(['spell2Id','key'],axis = 1)
df4 = pd.merge(df4,item_df,how = 'left', left_on = 'item0', right_on = 'key')
df4 = df4.rename(columns={'name': 'Item1'}).drop(['item0','key'],axis = 1)
df4 = pd.merge(df4,item_df,how = 'left', left_on = 'item1', right_on = 'key')
df4 = df4.rename(columns={'name': 'Item2'}).drop(['item1','key'],axis = 1)
df4 = pd.merge(df4,item_df,how = 'left', left_on = 'item2', right_on = 'key')
df4 = df4.rename(columns={'name': 'Item3'}).drop(['item2','key'],axis = 1)
df4 = pd.merge(df4,item_df,how = 'left', left_on = 'item3', right_on = 'key')
df4 = df4.rename(columns={'name': 'Item4'}).drop(['item3','key'],axis = 1)
df4 = pd.merge(df4,item_df,how = 'left', left_on = 'item4', right_on = 'key')
df4 = df4.rename(columns={'name': 'Item5'}).drop(['item4','key'],axis = 1)
df4 = pd.merge(df4,item_df,how = 'left', left_on = 'item5', right_on = 'key')
df4 = df4.rename(columns={'name': 'Item6'}).drop(['item5','key'],axis = 1)
df4 = pd.merge(df4,item_df,how = 'left', left_on = 'item6', right_on = 'key')
df4 = df4.rename(columns={'name': 'Trinket'}).drop(['item6','key'],axis = 1)
- 같은 방법으로 스펠과 아이템의 이름을 확인하기 위해 merge한다.
# 확인할 변수
COLUMNS_NEW = ["participantId", "teamId","win", "Champion", "D", "F", "KDA",
"kills","deaths","assists","Item1","Item2","Item3","Item4","Item5","Item6","Trinket","GPM","DPM","DTPM"]
df5 = df4[COLUMNS_NEW]
df5
participantId | teamId | win | Champion | D | F | KDA | kills | deaths | assists | Item1 | Item2 | Item3 | Item4 | Item5 | Item6 | Trinket | GPM | DPM | DTPM | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1 | 100 | False | 징크스 | 회복 | 점멸 | 2.500000 | 7 | 6 | 8 | 도란의 검 | 돌풍 | 고속 연사포 | 광전사의 군화 | B.F. 대검 | 곡괭이 | 망원형 개조 | 368.086957 | 3189.130435 | 620.869565 |
1 | 2 | 100 | False | 비에고 | 점멸 | 강타 | 1.777778 | 6 | 9 | 10 | 몰락한 왕의 검 | 충전형 물약 | 판금 장화 | NaN | NaN | 신성한 파괴자 | 예언자의 렌즈 | 337.378882 | 3148.732919 | 1228.322981 |
2 | 3 | 100 | False | 자이라 | 점멸 | 점화 | 2.333333 | 3 | 6 | 11 | 리안드리의 고뇌 | 망가진 초시계 | 얼음 정수의 파편 | 마법사의 신발 | 추적자의 팔목 보호대 | 루비 수정 | 예언자의 렌즈 | 281.925466 | 1408.211180 | 460.546584 |
3 | 4 | 100 | False | 애니비아 | 순간이동 | 점멸 | 1.600000 | 4 | 5 | 4 | 대천사의 포옹 | 리안드리의 고뇌 | NaN | NaN | 마법사의 신발 | NaN | 예언자의 렌즈 | 306.968944 | 3765.763975 | 539.105590 |
4 | 5 | 100 | False | 레넥톤 | 점멸 | 점화 | 1.000000 | 5 | 7 | 2 | 선혈포식자 | 충전형 물약 | 가시 갑옷 | 판금 장화 | 도란의 방패 | NaN | 예언자의 렌즈 | 310.993789 | 2623.490683 | 1105.453416 |
5 | 6 | 200 | True | 트런들 | 순간이동 | 점멸 | 2.800000 | 3 | 5 | 11 | 판금 장화 | 도란의 방패 | 신성한 파괴자 | 온기가 필요한 자의 도끼 | 망자의 갑옷 | 덤불 조끼 | 투명 와드 | 407.701863 | 4010.645963 | 1023.354037 |
6 | 7 | 200 | True | 아칼리 | 점화 | 점멸 | 3.500000 | 2 | 2 | 5 | 도란의 방패 | 마법사의 신발 | 존야의 모래시계 | 증폭의 고서 | 균열 생성기 | NaN | 투명 와드 | 313.677019 | 2386.360248 | 501.204969 |
7 | 8 | 200 | True | 카르마 | 점화 | 점멸 | 4.500000 | 0 | 4 | 18 | 얼음 정수의 파편 | 슈렐리아의 군가 | 제어 와드 | 화학공학 부패기 | 명석함의 아이오니아 장화 | NaN | 예언자의 렌즈 | 288.037267 | 829.378882 | 364.583851 |
8 | 9 | 200 | True | 킨드레드 | 강타 | 점멸 | 4.285714 | 23 | 7 | 7 | 헤르메스의 시미터 | 수호 천사 | 광전사의 군화 | 크라켄 학살자 | 징수의 총 | 고속 연사포 | 예언자의 렌즈 | 685.118012 | 7488.037267 | 928.472050 |
9 | 10 | 200 | True | 자야 | 회복 | 점멸 | 1.714286 | 5 | 7 | 7 | 도란의 검 | 돌풍 | 정수 약탈자 | B.F. 대검 | NaN | 광전사의 군화 | 망원형 개조 | 390.372671 | 4358.459627 | 506.161491 |
-
최종적으로 이 게임의 정보에 대해 위와 같이 확인 가능하다.
-
이 게임은 red팀이 승리하였고 킨드레드가 하드캐리한 것이 KDA, DPM 등을 통해 보인다.
Leave a comment