【发布时间】:2019-07-08 10:55:32
【问题描述】:
我知道我正在接近这一点,但我无法让散景来做我正在寻找的东西。我需要将时间数据重新采样为 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 使用这些数据做一些事情。 This instruction from bokeh 似乎给出了正确的方向;但是,它只使用一个 groupby。 This instruction from 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,as per these instructions,
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
)
我在设置图形时收到以下错误,即使这似乎是the format explained here:
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')]
我也尝试了其他一些方法,但这似乎是我得到的最接近的方法。希望对数据框的结构有任何见解,或者我缺少的任何其他愚蠢的错误。
感谢您的帮助!
编辑 所以我注意到最后一个错误不是关于数据结构,而是关于数据类型。所以我将日期时间转换为字符串:
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])
仍然愿意接受更多惯用的解决方案。
【问题讨论】:
-
您能在此处或要点中提供一个小样本数据集吗?
标签: python dataframe bokeh hierarchical-data