Привет, Хабр. Пишу впервые на Хабре и пишу затем, чтобы не только помочь вам, ув. читатели, но и себе вашими замечаниями и всем таким.

Для кого заметка?

Для тех кто получил ответ от яндекс метрики и хочет сделать с ним что-нибудь в 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 параметр.

После цикла я джоиню показатели и пишу столбцы которые лично я хочу видеть у себя в КХД, а после этог оеще и дописываю столбцы переданные в кваргах.

Получается такая красота:

Или такая: