Я знаю, что приближаюсь к этому, но я просто не могу заставить боке делать то, что я ищу.Мне нужно повторно выбрать временные данные в 15-минутные интервалы, затем сгруппировать их по иерархическим категориальным типам и отобразить результаты по временным группам.Буду признателен за любую помощь.
У меня есть данные, которые выглядят следующим образом:
basket_id food_type classified_time dipped_time slot_number
0 185261 CHICKEN FILLETS 2019-07-07 11:38:23.153858 2019-07-07 11:38:40.271070 8
1 185263 CHICKEN FILLETS 2019-07-07 11:38:25.831668 2019-07-07 11:38:53.265553 4
2 185273 CRISPY CHICKEN TENDERS 2019-07-07 11:39:26.184932 2019-07-07 11:39:58.164302 5
3 185276 CRISPY CHICKEN TENDERS 2019-07-07 11:39:30.178273 2019-07-07 11:39:46.076617 1
...
Я могу повторно сэмплировать эти данные, чтобы получить этот результат, который выглядит очень похоже на правильный путь:
agg_15m = df[['dipped_time', 'food_type']] \
.set_index('dipped_time', 'food_type') \
.groupby('food_type') \
.resample('15Min') \
.agg({'food_type': 'count'}) \
.rename(columns={'food_type':'COUNT'}) \
.reset_index()
display(agg_15m)
Затем я могу использовать groupby, чтобы получить правильную структуру:
group = agg_15m.groupby(['dipped_time', 'food_type'])
display(group.sum())
Само по себе это потребовало немало времени на диаграммах данных, так как я не очень знаком с концепциями работы с многоиндексированными данными.
Теперь самое интересное - попытаться заставить Боке что-то сделать с этими данными. Эта инструкция от боке , кажется, дает правильное направление;однако, он использует только одну группу. Эта инструкция от bokeh дает некоторое направление для иерархических категориальных данных, но пример сделан с использованием только литералов.
Итак, вот что я попробовал.
p = figure(
title="Baskets Cooked per 15min",
y_axis_label="Count",
plot_width=plot_width,
plot_height=plot_height,
toolbar_location=toolbar_loc,
)
p.vbar(x='dipped_time_food_type', top='COUNT', width=1e3*60*15, source=self.group.sum() )
Это дает пустой график
Если я попытаюсь поместить объект группы в x_range, согласно этим инструкциям ,
self.p = figure(
title="Baskets Cooked per 15min",
y_axis_label="Count",
plot_width=plot_width,
plot_height=plot_height,
toolbar_location=toolbar_loc,
x_range=group
)
Я получаю следующую ошибку при настройке фигуры, хотя кажется, что это формат, описанный здесь :
ValueError: expected an element of either Seq(String), Seq(Tuple(String, String)) or Seq(Tuple(String, String, String)), got [(Timestamp('2019-07-07 11:30:00'), 'CHICKEN FILLETS'), (Timestamp('2019-07-07 11:30:00'), 'CRISPY CHICKEN TENDERS'), (Timestamp('2019-07-07 11:30:00'), 'POPCORN CHICKEN'), (Timestamp('2019-07-07 11:30:00'), 'POTATO FRIES'), (Timestamp('2019-07-07 11:45:00'), 'CHICKEN FILLETS'), (Timestamp('2019-07-07 11:45:00'), 'CRISPY CHICKEN TENDERS'), (Timestamp('2019-07-07 11:45:00'), 'POPCORN CHICKEN'), (Timestamp('2019-07-07 11:45:00'), 'POTATO FRIES'), (Timestamp('2019-07-07 12:00:00'), 'CHICKEN FILLETS'), (Timestamp('2019-07-07 12:00:00'), 'CRISPY CHICKEN TENDERS'), (Timestamp('2019-07-07 12:00:00'), 'POPCORN CHICKEN'), (Timestamp('2019-07-07 12:00:00'), 'POTATO FRIES'), (Timestamp('2019-07-07 12:15:00'), 'CHICKEN FILLETS'), (Timestamp('2019-07-07 12:15:00'), 'CRISPY CHICKEN TENDERS'), (Timestamp('2019-07-07 12:15:00'), 'POPCORN CHICKEN'), (Timestamp('2019-07-07 12:15:00'), 'POTATO FRIES'), (Timestamp('2019-07-07 12:30:00'), 'CHICKEN FILLETS'), (Timestamp('2019-07-07 12:30:00'), 'CRISPY CHICKEN TENDERS'), (Timestamp('2019-07-07 12:30:00'), 'POPCORN CHICKEN'), (Timestamp('2019-07-07 12:30:00'), 'POTATO FRIES'), (Timestamp('2019-07-07 12:45:00'), 'CRISPY CHICKEN TENDERS'), (Timestamp('2019-07-07 12:45:00'), 'POPCORN CHICKEN'), (Timestamp('2019-07-07 12:45:00'), 'POTATO FRIES'), (Timestamp('2019-07-07 13:00:00'), 'CRISPY CHICKEN TENDERS'), (Timestamp('2019-07-07 13:00:00'), 'POTATO FRIES'), (Timestamp('2019-07-07 13:15:00'), 'CRISPY CHICKEN TENDERS'), (Timestamp('2019-07-07 13:15:00'), 'POTATO FRIES'), (Timestamp('2019-07-07 13:30:00'), 'CRISPY CHICKEN TENDERS'), (Timestamp('2019-07-07 13:30:00'), 'POTATO FRIES'), (Timestamp('2019-07-07 13:45:00'), 'POTATO FRIES'), (Timestamp('2019-07-07 14:00:00'), 'POTATO FRIES'), (Timestamp('2019-07-07 14:15:00'), 'POTATO FRIES')]
I 'Мы также попробовали несколько других вещей, но это, кажется, самое близкое, что я получил.Хотелось бы получить представление о структуре данных или любую другую глупую ошибку, которую мне не хватает.
Спасибо за помощь!
Редактировать Итак, я заметил, что последняя ошибка была не о структуре данных, а о типах данных.Поэтому я преобразовал datetime в строки:
agg_15m = df[['dipped_time', 'food_type']] \
.set_index('dipped_time', 'food_type') \
.groupby('food_type') \
.resample('15Min') \
.agg({'food_type': 'count'}) \
.rename(columns={'food_type':'COUNT'}) \
.reset_index()
agg_15m['dipped_time'] = agg_15m['dipped_time'].to_string()
self.group = agg_15m.groupby(['dipped_time', 'food_type'])
self.p = figure(
title="Baskets Cooked per 15min",
y_axis_label="Count",
plot_width=plot_width,
plot_height=plot_height,
toolbar_location=toolbar_loc,
x_range=self.group
)
self.p.vbar(x='dipped_time_food_type', top='COUNT_std', width=1, source=ColumnDataSource(self.group))
Теперь это дает мне довольно уродливый график, который, кажется, не представляет базовые данные.
Я пытаюсь найти что-то более похожее на это:
РЕДАКТИРОВАТЬ
Последняя версия преобразования строки была неправильной.Обновлено до
agg_15m = df[['dipped_time', 'food_type']] \
.set_index('dipped_time', 'food_type') \
.groupby('food_type') \
.resample('15Min') \
.agg({'food_type': 'count'}) \
.rename(columns={'food_type':'COUNT'}) \
.reset_index()
agg_15m['dipped_time'] = agg_15m['dipped_time'].astype(str)
self.group = agg_15m.groupby(['dipped_time', 'food_type'])
self.p = figure(
title="Baskets Cooked per 15min",
y_axis_label="Count",
plot_width=plot_width,
plot_height=plot_height,
toolbar_location=toolbar_loc,
x_range=self.group
)
self.p.vbar(x='dipped_time_food_type', top='COUNT_std', width=1, source=ColumnDataSource(self.group))
Это дает правильные данные, но теперь график пуст с некоторыми артефактами в углу.
РЕДАКТИРОВАТЬ
Я не мог заставить его работать, поэтому я пошел на ручной метод.Этот код работает:
df['dipped_time'] = pd.to_datetime(df['dipped_time'], errors='coerce') #convert to datetime so we can resample
#group by food and resample to 15min intervals
agg_15m = df[['dipped_time', 'food_type']] \
.set_index('dipped_time', 'food_type') \
.groupby('food_type') \
.resample('15Min') \
.agg({'food_type': 'count'}) \
.rename(columns={'food_type':'COUNT'}) \
.reset_index()
agg_15m['dipped_time'] = agg_15m['dipped_time'].astype(str)
plot_width = 800
plot_height = 600
toolbar_loc = 'above'
self.p = figure(
title="Baskets Cooked per 15min",
y_axis_label="Count",
plot_width=plot_width,
plot_height=plot_height,
toolbar_location=toolbar_loc,
x_range=sorted(self.agg_15m.dipped_time.unique())
)
self.food_types = self.agg_15m.food_type.unique()
self.data_source = dict(
x=sorted(self.agg_15m.dipped_time.unique())
)
df = self.agg_15m
for food_type in self.food_types:
arr = []
for time in sorted(self.agg_15m.dipped_time.unique()):
if df.loc[(df["dipped_time"]==time) & (df["food_type"]==food_type), "COUNT"].empty:
arr.append(0)
else:
arr.append(df.loc[(df["dipped_time"]==time) & (df["food_type"]==food_type), "COUNT"].values[0])
self.data_source[food_type] = arr
fill_colors=[
Spectral5[i]
for i in range(len(self.food_types))]
self.p.vbar_stack(self.food_types, \
x='x', \
width=0.9, alpha=0.5, \
source=ColumnDataSource(self.data_source), \
fill_color=fill_colors,
legend=[value(x) for x in self.food_types])
Все еще открыт для более идиоматических решений.