Изучение новейшей истории электростанций внутреннего сгорания в Нидерландах.

Часть 2. Страшный на первый взгляд, но пушистый внутри. Обратите внимание, почему вы должны использовать многоиндексные (иерархические) фреймы данных.

Ниже я кратко представляю свои размышления о мультииндексных фреймах данных. За результатами переходите к части 1. За кодом — сюда. Если вы ищете хороший вводный учебник, я настоятельно рекомендую вам это или это.

Если вы, как и я, интересуетесь анализом временных рядов, вам всегда будет сложно найти способ добавить измерение времени наиболее репрезентативным образом. На самом деле, я до сих пор помню свою первую попытку исследовать набор данных временных рядов значительного размера, сколько разочарований мне потребовалось, чтобы решить, что делать, чтобы не потерять связь с временными особенностями данных. Что, если бы я сказал вам, что теперь я убежден, что мультииндексные фреймы данных — лучший способ сделать это?

Наш мозг может воспринимать 3 (или даже больше) измерения, так почему кадры данных должны ограничиваться исключительно 2D. Понятно, что это противоречит идее уменьшения размерности, но в некоторых случаях лучше не переусердствовать.

Функциональность мультииндекса в пандах уже давно растет, но у меня все еще есть ощущение, что она не получила достаточного признания.

Позвольте мне затронуть, возможно, основную тревогу новичка в мультииндексации: мультииндексные фреймы данных кажутся громоздкими в обращении. Однако ничто не может быть дальше от реальности. Вот несколько могущественных союзников, которые помогут вам.

Союзник №1. Сгруппировать по.

Эта функция эффективно позволяет быстро и безболезненно переключаться между уровнями фрейма данных.

Союзник №2. Складывать/разбирать.

Устали от мультииндексации? Перейдите в 2D с любой индексацией, которую вы хотите.

Союзник №3. Другие функции панд.

В последних выпусках многие функции Python имеют аргумент «уровень», который указывает, к какому индексу он должен применяться.

Для демонстрации позвольте мне представить пример 2 функций очистки данных.

def pollution_change_spotter_plants(dfx, threshold):
    """
    Calculate amount of pollutant-years per each plant from 2007 to 2015.
    Pollutant-year - a relative measure of power plant performance. One pollutant year corresponds to a (one) year
    when the particular emissions were higher than in 2015.
    Input: multiindex dataframe created earlier, threshold value for comparison with 2015 - by default 1.
    Output: regular dataframe
    """
    dfx = dfx[["NOx", "SO2", "Dust"]].copy()
    dfx = dfx.groupby(level=0).apply(lambda x : x.iloc[-1]/x)
    df_changed_plants = dfx[dfx < threshold] #selecting plants which polluted more than in 2015
    df_changed_plants =        df_changed_plants[~df_changed_plants.index.isin(["2015"], level=1)] #dropping 2015
    df_changed_plants = len(dfx.groupby(level=1))-df_changed_plants.groupby(level=0).apply(lambda x: x.isna().sum(axis=0)) -1 #number of more polluted years than 2015
    
    return df_changed_plants

И

def pollution_change_spotter_years(dfx, threshold):
    """
    Calculate amount of power plants per year, whose pollution in a given year was more than in 2015.
    Input: multiindex dataframe created earlier, threshold value for comparison with 2015 - by default 1.
    Output: regular dataframe
    """
    dfx = dfx[["NOx", "SO2", "Dust"]].copy()
    dfx = dfx.groupby(level=0).apply(lambda x : x.iloc[-1]/x).replace(0,np.nan) #if result of lambda x >1 -> polluted less than in 2015
    df_changed_years = dfx[dfx < threshold] #selecting plants which polluted more than in 2015
    df_changed_years = len(dfx.groupby(level=0)) - df_changed_years.groupby(level=1).apply(lambda x: x.isna().sum(axis=0)) -1#number of polluted more
    df_changed_years.drop(df_changed_years.tail(1).index,inplace=True)
    return df_changed_years

Самая существенная строка в них:

df_changed_years = len(dfx.groupby(level=n)) - df_changed_years.groupby(level=m).apply(lambda x: x.isna().sum(axis=0)

Единственным отличием является изменение уровня индекса. Тем не менее, это помогает всесторонне анализировать и комбинировать функции на указанной оси. Такие функции могут быть созданы для следующих уровней фрейма данных и обеспечивают значительное улучшение логики и эффективности очистки данных по сравнению с двумерными фреймами данных.

Многоиндексирование – это быстрый и надежный способ манипулирования данными так, как вы их воспринимаете.