Построение фрейма данных с перечислениями в качестве значений

#python #python-3.x #pandas #dataframe #enums

#python #python-3.x #панды #фрейм данных #перечисления

Вопрос:

У меня есть некоторые данные:

 data = pd.DataFrame(data=[(1, 1), (2, 1), (2, 5), (0, 2), (1, 4), (0, 1)])
 

Первый столбец должен быть enum:

 class Type(Enum): 
    OFF = 0
    PARTIAL = 1
    FULL = 2
    def __str__(self):
      return self.name

data[0] = data[0].apply(lambda x: Type(x))
 

Теперь у нас есть таблица:

          0  1
0  PARTIAL  1
1     FULL  1
2     FULL  5
3      OFF  2
4  PARTIAL  4
5      OFF  1
 

И я хочу иметь возможность легко отображать эти данные с помощью команды:

 data.plot()
 

Есть ли какой-нибудь способ сделать это?
Потому что сейчас мне нужно разделить его на два фрейма данных и построить их отдельно:

 data[0].apply(lambda x: x.value).plot()
data[1].plot()
 

Комментарии:

1. Просто чтобы правильно понять: вы хотите, чтобы значения enum снова были целыми числами на вашем графике?

Ответ №1:

Я понял это, но решение не рекомендуется:

Я создал функцию, которая проверяет, есть ли у нас перечисление в фрейме данных, и заменяет его соответствующими значениями:

   def plot_df(df, **input_data):
    if isinstance(df, pd.DataFrame):
        df_copy = df.copy()
        for frame in df:
            if isinstance(df[frame].all(), Enum):
                df_copy[frame] = df[frame].apply(lambda x: x.value)
        df_copy.plot(**input_data)
    elif isinstance(df, pd.Series):
        df_copy = df.copy()
        if isinstance(df.all(), Enum):
            df_copy = df.apply(lambda x: x.value)
        df_copy.plot(**input_data)
    else:
        raise TypeError('data should be Dataframe or Series')
 

Теперь мы добавляем метод к существующему экземпляру объекта (что не рекомендуется).:

 import types
data.plot = types.MethodType(plot_df, data)
 

И теперь мы можем сделать:

 data.plot()
 

Ответ №2:

 import pandas as pd
from enum import Enum


def plot_enum_df(df, **input_data):
    if isinstance(df, pd.DataFrame):
        df_copy = df.copy()
        for frame in df:
            if isinstance(df[frame].all(), Enum):
                df_copy[frame] = df[frame].apply(lambda x: x.value)
        df_copy.plot(**input_data)
    else:
        raise TypeError('Data should be DataFrame')


def plot_enum_s(series, **input_data):
    if isinstance(series, pd.Series):
        s_copy = series.copy()
        if isinstance(series.all(), Enum):
            s_copy = series.apply(lambda x: x.value)
        s_copy.plot(**input_data)
    else:
        raise TypeError('Data should be Series')


def plot_enum_config():
    pd.DataFrame.plot_enum = plot_enum_df
    pd.Series.plot_enum = plot_enum_s
 

В начале кода мы должны поместить:

 plot_enum_config()
 

И теперь мы можем сделать:

 data.plot_enum()
 

Ответ №3:

Я знаю, что у вас уже есть ответ, я просто хотел добавить альтернативы.

Я предполагаю, что здесь вы хотите использовать перечисления для организации своей проблемы. Перечисления имеют числовую структуру, и имеет смысл отображать их в виде чисел на линейном графике. Затем, чтобы создать график только с data.plot() помощью, я бы использовал IntEnum примерно так:

 import pandas as pd
from enum import IntEnum

class Type(IntEnum):
    OFF = 0
    PARTIAL = 1
    FULL = 2

data = pd.DataFrame(data=[(1, 1), (2, 1), (2, 5), (0, 2), (1, 4), (0, 1)])
data[0] = data[0].apply(lambda x: Type(x))

data.plot()
 

В качестве альтернативы вы можете использовать pandas Categorical, чтобы иметь что-то эквивалентное enum в pandas, например data[0] = data[0].apply(lambda x: Type(x)).astype("category") . Но это не помогает data.plot() напрямую решить вашу проблему.