#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()
напрямую решить вашу проблему.