Превращаем ответ Api Яндекс Appmetrica в pandas DataFrame
Привет, Хабр. Пишу впервые на Хабре и пишу затем, чтобы не только помочь вам, ув. читатели, но и себе вашими замечаниями и всем таким.
Для кого заметка?
Для тех кто получил ответ от яндекс метрики и хочет сделать с ним что-нибудь в pandas.
В чем проблема?
Можно же получить ответ в формате CSV от https://api.appmetrica.yandex.ru/stat/v1/data.csv и в одну строчку ( pd.read_csv(io.StringIO(response.text), sep=",") ) получить не делать себе мозг. Человекочитаемый результат перед глазами

Однако простые пути не для нас, у нас появляется лишняя строчка с итого и масса кириллицы и в конце концов мы теряем важную инфу о свойствах самого ответа, включая возможное семплирование, округление, общее колво строк, настройки и все такое. Особенно важны они бывают если запросы генерируются автоматически и должны обрабатываться в зависимости от содержимого.
Решение:
По этому имхо важно получить жисон и переконвертнуть его в датафрейм.
# -------- НОВАЯ ПРЕВРАЩАЛКА ОТВЕТА V1 В ДФ!
def appmetrica_v1_response_to_df(response, **kwargs):
'''
Принимаем респонз из https://api.appmetrica.yandex.ru/stat/v1/data
в кварги можно добавить словарь add_columns в формате {"столбец":"значение"}
'''
add_columns = kwargs['add_columns'] if 'add_columns' in kwargs else {}
if len(response['data']) == 0:
return (pd.DataFrame())
df = pd.DataFrame.from_dict(response['data'])
pre_dimensions = pd.DataFrame(df['dimensions'].to_list(),columns = response['query']['dimensions'])
pre_metrics = pd.DataFrame(df['metrics'].to_list(),columns = response['query']['metrics'])
dimensions = pd.DataFrame()
for dimension in pre_dimensions.columns:
current_dimension = pd.DataFrame(pre_dimensions[dimension].to_list())
current_dimension.columns = [dimension + '_' + column if column != 'name' else dimension for column in current_dimension]
dimensions = dimensions.join(current_dimension, how = 'right')
df = dimensions.join(pre_metrics)
df['sample_share'] = response['sample_share']
df['ids'] = str(response['query']['ids'][0])
for key,values in add_columns.items():
df[key] = values
return (df)
appmetrica_v1_response_to_df(test2, add_columns = {'ym:i:device_filter':'Google Play'})Обращаю внимние, что эта функция поможет только с ответами от первой версии апи отчетов. Для второй я еще не сделал.
В коде собственно:
add_columns = kwargs['add_columns'] if 'add_columns' in kwargs else {}прием словаря на случай если необходимо прописать дополнительные колонки. Например, если мы взяли репорт с фильтром и хотим сохранить его в столбце. Вот пример вызова
appmetrica_v1_response_to_df(test2, add_columns = {'ym:i:device_filter':'Google Play'})для отчета по треккеру Google Play, о чем мы хотим построчно сообщить в отдельном столбце.
Проверяем не пустой ли отчет, чтобы вернуть в случае чего пустой датафрейм а не ошибку:
if len(test2['data']) == 0:
return (pd.DataFrame())Эту проверку я кстати забыл сделать в первой версии статьи, но исправил еще до того как она ушла на модерацию. А переребор и конкатенация нескольких выгрузок это мне запороло.
Все данные в отчете хранятся в response['data'] и легко превращаются вот в такую порнографию:

Таким образом мы разбиваем параметры и показатели на столбцы:
pre_dimensions = pd.DataFrame(df['dimensions'].to_list(),columns = response['query']['dimensions'])
pre_metrics = pd.DataFrame(df['metrics'].to_list(),columns = response['query']['metrics'])в каждом из которых будут словарики для параметров

и готовые столбцы с показателями.
Далее в цикле мы перебираем столбцы с параметрами,поднимаем их еще раз из словаря в датафрейм, и переименовываем их в зависимости от заголовка получившейся колонки. Дело в том что аппметрика может отдать не только название показателя, но, например, еще и его его идентификатор:
{'dimensions': [{'id': '4', 'name': 'Trololo1'}], 'metrics': [5.0]}, {'dimensions': [{'id': '5', 'name': 'Unconfigured Trololo2'}], 'metrics': [4.0]}, {'dimensions': [{'id': '964618551316972214', 'name': 'agency Trololo3'}], 'metrics': [4.0]},
В цикле я переименовываю колонки которые НЕ называются name в название параметра + префикс из такой вот разновидности "параметров параметров", а name в сам параметр.
current_dimension = pd.DataFrame(pre_dimensions[dimension].to_list())
current_dimension.columns = [dimension + '_' + column if column != 'name' else dimension for column in current_dimension]
dimensions = dimensions.join(current_dimension, how = 'right')Получаются столбцы "Параметр_id" и "Параметр" на каждый параметр. разумеется, если параметр отдел только name на параметр получается только 1 параметр.
После цикла я джоиню показатели и пишу столбцы которые лично я хочу видеть у себя в КХД, а после этог оеще и дописываю столбцы переданные в кваргах.
Получается такая красота:

Или такая:
