#python #json #pandas
#python #json #pandas
Вопрос:
Я извлек коэффициенты игры в НФЛ из-odds-api. Используя pd.io.json.json_normalize, я могу создать фрейм данных, но данные недостаточно разбиты, чтобы удовлетворить мои потребности, поскольку все коэффициенты находятся в одном столбце.
Пример первой нормализованной записи:
apidownload = {'sport_key': 'americanfootball_nfl', 'sport_nice': 'NFL', 'teams': ['Houston Texans', 'Kansas City Chiefs'], 'commence_time': 1599783600, 'home_team': 'Kansas City Chiefs', 'sites': [{'site_key': 'unibet', 'site_nice': 'Unibet', 'last_update': 1598541677, 'odds': {'spreads': {'odds': [1.91, 1.91], 'points': ['10.0', '-10.0']}}}, {'site_key': 'pointsbetus', 'site_nice': 'PointsBet (US)', 'last_update': 1598541706, 'odds': {'spreads': {'odds': [1.87, 1.95], 'points': ['10.5', '-10.5']}}}, {'site_key': 'gtbets', 'site_nice': 'GTbets', 'last_update': 1598541568, 'odds': {'spreads': {'odds': [1.877, 1.962], 'points': ['10', '-10']}}}, {'site_key': 'mybookieag', 'site_nice': 'MyBookie.ag', 'last_update': 1598541546, 'odds': {'spreads': {'odds': [1.87, 1.95], 'points': ['10.0', '-10.0']}}}, {'site_key': 'draftkings', 'site_nice': 'DraftKings', 'last_update': 1598541517, 'odds': {'spreads': {'odds': [1.91, 1.91], 'points': ['10.0', '-10.0']}}}, {'site_key': 'fanduel', 'site_nice': 'FanDuel', 'last_update': 1598541405, 'odds': {'spreads': {'odds': [2.0, 1.83], 'points': ['9.5', '-9.5']}}}, {'site_key': 'intertops', 'site_nice': 'Intertops', 'last_update': 1598541645, 'odds': {'spreads': {'odds': [1.9091, 1.9091], 'points': ['10.00', '-10.00']}}}, {'site_key': 'williamhill_us', 'site_nice': 'William Hill (US)', 'last_update': 1598541617, 'odds': {'spreads': {'odds': [1.87, 1.95], 'points': ['10.0', '-10.0']}}}, {'site_key': 'betrivers', 'site_nice': 'BetRivers', 'last_update': 1598541683, 'odds': {'spreads': {'odds': [1.91, 1.91], 'points': ['10.0', '-10.0']}}}], 'sites_count': 9}
df = pd.io.json.json_normalize(apidownload)
df
имеет 7 столбцов с col6 «сайтами», содержащих все коэффициенты из 9 источников
odds = pd.io.json.json_normalize(df.sites[0])
odds
разбивает 9 источников, но в новом фрейме данных с 9 строками. У меня возникли проблемы с выяснением, как это сделать в одном и том же фрейме данных, чтобы он отображал информацию о команде / игре с соответствующими коэффициентами из каждого источника в отдельных столбцах.
Ответ №1:
Не уверен, как именно вы хотите, чтобы конечный результат выглядел, но в прошлом мне приходилось нормализовать вложенный файл json, и я использовал эту небольшую функцию для выравнивания вложенной структуры, а затем восстановления таблицы. Посмотрите, является ли это тем, что вы ищете:
apidownload = {'sport_key': 'americanfootball_nfl', 'sport_nice': 'NFL', 'teams': ['Houston Texans', 'Kansas City Chiefs'], 'commence_time': 1599783600, 'home_team': 'Kansas City Chiefs', 'sites': [{'site_key': 'unibet', 'site_nice': 'Unibet', 'last_update': 1598541677, 'odds': {'spreads': {'odds': [1.91, 1.91], 'points': ['10.0', '-10.0']}}}, {'site_key': 'pointsbetus', 'site_nice': 'PointsBet (US)', 'last_update': 1598541706, 'odds': {'spreads': {'odds': [1.87, 1.95], 'points': ['10.5', '-10.5']}}}, {'site_key': 'gtbets', 'site_nice': 'GTbets', 'last_update': 1598541568, 'odds': {'spreads': {'odds': [1.877, 1.962], 'points': ['10', '-10']}}}, {'site_key': 'mybookieag', 'site_nice': 'MyBookie.ag', 'last_update': 1598541546, 'odds': {'spreads': {'odds': [1.87, 1.95], 'points': ['10.0', '-10.0']}}}, {'site_key': 'draftkings', 'site_nice': 'DraftKings', 'last_update': 1598541517, 'odds': {'spreads': {'odds': [1.91, 1.91], 'points': ['10.0', '-10.0']}}}, {'site_key': 'fanduel', 'site_nice': 'FanDuel', 'last_update': 1598541405, 'odds': {'spreads': {'odds': [2.0, 1.83], 'points': ['9.5', '-9.5']}}}, {'site_key': 'intertops', 'site_nice': 'Intertops', 'last_update': 1598541645, 'odds': {'spreads': {'odds': [1.9091, 1.9091], 'points': ['10.00', '-10.00']}}}, {'site_key': 'williamhill_us', 'site_nice': 'William Hill (US)', 'last_update': 1598541617, 'odds': {'spreads': {'odds': [1.87, 1.95], 'points': ['10.0', '-10.0']}}}, {'site_key': 'betrivers', 'site_nice': 'BetRivers', 'last_update': 1598541683, 'odds': {'spreads': {'odds': [1.91, 1.91], 'points': ['10.0', '-10.0']}}}], 'sites_count': 9}
import pandas as pd
import re
def flatten_json(y):
out = {}
def flatten(x, name=''):
if type(x) is dict:
for a in x:
flatten(x[a], name a '_')
elif type(x) is list:
i = 0
for a in x:
flatten(a, name str(i) '_')
i = 1
else:
out[name[:-1]] = x
flatten(y)
return out
flat = flatten_json(apidownload)
results = pd.DataFrame()
special_cols = []
columns_list = list(flat.keys())
for item in columns_list:
try:
row_idx = re.findall(r'_(d )_', item )[0]
except:
special_cols.append(item)
continue
column = re.findall(r'_d _(.*)', item )[0]
row_idx = int(row_idx)
value = flat[item]
results.loc[row_idx, column] = value
for item in special_cols:
results[item] = flat[item]
Вывод:
print(results.to_string())
site_key site_nice last_update odds_spreads_odds_0 odds_spreads_odds_1 odds_spreads_points_0 odds_spreads_points_1 sport_key sport_nice teams_0 teams_1 commence_time home_team sites_count
0 unibet Unibet 1.598542e 09 1.9100 1.9100 10.0 -10.0 americanfootball_nfl NFL Houston Texans Kansas City Chiefs 1599783600 Kansas City Chiefs 9
1 pointsbetus PointsBet (US) 1.598542e 09 1.8700 1.9500 10.5 -10.5 americanfootball_nfl NFL Houston Texans Kansas City Chiefs 1599783600 Kansas City Chiefs 9
2 gtbets GTbets 1.598542e 09 1.8770 1.9620 10 -10 americanfootball_nfl NFL Houston Texans Kansas City Chiefs 1599783600 Kansas City Chiefs 9
3 mybookieag MyBookie.ag 1.598542e 09 1.8700 1.9500 10.0 -10.0 americanfootball_nfl NFL Houston Texans Kansas City Chiefs 1599783600 Kansas City Chiefs 9
4 draftkings DraftKings 1.598542e 09 1.9100 1.9100 10.0 -10.0 americanfootball_nfl NFL Houston Texans Kansas City Chiefs 1599783600 Kansas City Chiefs 9
5 fanduel FanDuel 1.598541e 09 2.0000 1.8300 9.5 -9.5 americanfootball_nfl NFL Houston Texans Kansas City Chiefs 1599783600 Kansas City Chiefs 9
6 intertops Intertops 1.598542e 09 1.9091 1.9091 10.00 -10.00 americanfootball_nfl NFL Houston Texans Kansas City Chiefs 1599783600 Kansas City Chiefs 9
7 williamhill_us William Hill (US) 1.598542e 09 1.8700 1.9500 10.0 -10.0 americanfootball_nfl NFL Houston Texans Kansas City Chiefs 1599783600 Kansas City Chiefs 9
8 betrivers BetRivers 1.598542e 09 1.9100 1.9100 10.0 -10.0 americanfootball_nfl NFL Houston Texans Kansas City Chiefs 1599783600 Kansas City Chiefs 9
Комментарии:
1. Фактическая загрузка API содержит несколько записей (я воссоздал первую для своего вопроса), поэтому я получаю коэффициенты в отдельных столбцах, а не в строках.