【问题标题】:how to create a stacked bar chart indicating time spent on nest per day如何创建一个堆积条形图,指示每天花在筑巢上的时间
【发布时间】:2022-01-24 23:21:02
【问题描述】:

我有一些猫头鹰的数据存在于巢箱中。在上一个问题中,您帮助我想象猫头鹰何时在盒子里:

此外,我使用下面的代码创建了每天在框中花费的小时数的图(可能这可以更有效地完成):

import pandas as pd
import matplotlib.pyplot as plt

# raw data indicating time spent in box (each row represents start and end time)
time = pd.DatetimeIndex(["2021-12-01 18:08","2021-12-01 18:11",
                         "2021-12-02 05:27","2021-12-02 05:29",
                         "2021-12-02 22:40","2021-12-02 22:43",
                         "2021-12-03 19:24","2021-12-03 19:27",
                         "2021-12-06 18:04","2021-12-06 18:06",
                         "2021-12-07 05:28","2021-12-07 05:30",
                         "2021-12-10 03:05","2021-12-10 03:10",
                         "2021-12-10 07:11","2021-12-10 07:13",
                         "2021-12-10 20:40","2021-12-10 20:41",
                         "2021-12-12 19:42","2021-12-12 19:45",
                         "2021-12-13 04:13","2021-12-13 04:17",
                         "2021-12-15 04:28","2021-12-15 04:30",
                         "2021-12-15 05:21","2021-12-15 05:25",
                         "2021-12-15 17:40","2021-12-15 17:44",
                         "2021-12-15 22:31","2021-12-15 22:37",
                         "2021-12-16 04:24","2021-12-16 04:28",
                         "2021-12-16 19:58","2021-12-16 20:09",
                         "2021-12-17 17:42","2021-12-17 18:04",
                         "2021-12-17 22:19","2021-12-17 22:26",
                         "2021-12-18 05:41","2021-12-18 05:44",
                         "2021-12-19 07:40","2021-12-19 16:55",
                         "2021-12-19 20:39","2021-12-19 20:52",
                         "2021-12-19 21:56","2021-12-19 23:17",
                         "2021-12-21 04:53","2021-12-21 04:59",
                         "2021-12-21 05:37","2021-12-21 05:39",
                         "2021-12-22 08:06","2021-12-22 17:22",
                         "2021-12-22 20:04","2021-12-22 21:24",
                         "2021-12-22 21:44","2021-12-22 22:47",
                         "2021-12-23 02:20","2021-12-23 06:17",
                         "2021-12-23 08:07","2021-12-23 16:54",
                         "2021-12-23 19:36","2021-12-23 23:59:59",
                         "2021-12-24 00:00","2021-12-24 00:28",
                         "2021-12-24 07:53","2021-12-24 17:00",
                             ])

# create dataframe with column indicating presence (1) or absence (0)
time_df = pd.DataFrame(data={'present':[1,0]*int(len(time)/2)}, index=time)

# calculate interval length and add to time_df
time_df['interval'] = time_df.index.to_series().diff().astype('timedelta64[m]')

# add column with day to time_df
time_df['day'] = time.day

#select only intervals where owl is present 
timeinbox = time_df.iloc[1::2, :]
interval = timeinbox.interval
day = timeinbox.day

# sum multiple intervals per day
interval_tot = [interval[0]]
day_tot = [day[0]]
for i in range(1, len(day)):
    if day[i] == day[i-1]:
        interval_tot[-1] +=interval[i]
    else:
        day_tot.append(day[i])
        interval_tot.append(interval[i])

# recalculate to hours        
for i in range(len(interval_tot)):
    interval_tot[i] = interval_tot[i]/(60)

plt.figure(figsize=(15, 5))       
plt.grid(zorder=0)
plt.bar(day_tot, interval_tot, color='g', zorder=3) 

plt.xlim([1,31])
plt.xlabel('day in December')
plt.ylabel('hours per day in nest box')
plt.xticks(np.arange(1,31,1))
plt.ylim([0, 24])

现在我想通过制作一个堆积条形图将所有数据组合在一个图中,其中每一天都由一个条形表示,每个条形表示 24*60 分钟的每一分钟是否存在猫头鹰。从当前的数据结构来看,这可能吗?

【问题讨论】:

  • 我是否正确理解索引时间序列数据中的两列是第一列是他们进入巢穴的时间,第二列为他们离开巢穴的时间?
  • 确实如此!我记下了摄像机记录的进入时间和退出时间。由于数据量仍然相对较小,如果这样可以更轻松地处理 Pandas 中的数据,我仍然可以更改为其他结构。

标签: python pandas time-series stackedbarseries


【解决方案1】:

数据似乎是手动创建的,所以我更改了呈现数据的格式。我采用的方法是创建花费的时间和未花费的时间,以 1 分钟为间隔的连续索引,以开始和结束时间作为差异时间,标志为 1。现在要创建非停留时间,我将以 1 分钟的间隔创建开始和结束日期 + 1 的时间序列索引。使用新创建的索引更新原始数据框。这是图表的数据。在图中,根据提取的以天为单位的数据框,创建一个颜色列表,红色表示停留,绿色表示非停留。然后,在条形图中,堆叠高度一。可能有必要考虑将数据分组为小时单位。

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from datetime import timedelta
import io

data = '''
start_time,end_time
"2021-12-01 18:08","2021-12-01 18:11"
"2021-12-02 05:27","2021-12-02 05:29"
"2021-12-02 22:40","2021-12-02 22:43"
"2021-12-03 19:24","2021-12-03 19:27"
"2021-12-06 18:04","2021-12-06 18:06"
"2021-12-07 05:28","2021-12-07 05:30"
"2021-12-10 03:05","2021-12-10 03:10"
"2021-12-10 07:11","2021-12-10 07:13"
"2021-12-10 20:40","2021-12-10 20:41"
"2021-12-12 19:42","2021-12-12 19:45"
"2021-12-13 04:13","2021-12-13 04:17"
"2021-12-15 04:28","2021-12-15 04:30"
"2021-12-15 05:21","2021-12-15 05:25"
"2021-12-15 17:40","2021-12-15 17:44"
"2021-12-15 22:31","2021-12-15 22:37"
"2021-12-16 04:24","2021-12-16 04:28"
"2021-12-16 19:58","2021-12-16 20:09"
"2021-12-17 17:42","2021-12-17 18:04"
"2021-12-17 22:19","2021-12-17 22:26"
"2021-12-18 05:41","2021-12-18 05:44"
"2021-12-19 07:40","2021-12-19 16:55"
"2021-12-19 20:39","2021-12-19 20:52"
"2021-12-19 21:56","2021-12-19 23:17"
"2021-12-21 04:53","2021-12-21 04:59"
"2021-12-21 05:37","2021-12-21 05:39"
"2021-12-22 08:06","2021-12-22 17:22"
"2021-12-22 20:04","2021-12-22 21:24"
"2021-12-22 21:44","2021-12-22 22:47"
"2021-12-23 02:20","2021-12-23 06:17"
"2021-12-23 08:07","2021-12-23 16:54"
"2021-12-23 19:36","2021-12-24 00:00"
"2021-12-24 00:00","2021-12-24 00:28"
"2021-12-24 07:53","2021-12-24 17:00"
'''
df = pd.read_csv(io.StringIO(data), sep=',')
df['start_time'] = pd.to_datetime(df['start_time'])
df['end_time'] = pd.to_datetime(df['end_time'])

time_df = pd.DataFrame()
for idx, row in df.iterrows():
    rng = pd.date_range(row['start_time'], row['end_time']-timedelta(minutes=1), freq='1min')
    tmp = pd.DataFrame({'present':[1]*len(rng)}, index=rng)
    time_df = time_df.append(tmp)
date_add = pd.date_range(time_df.index[0].date(), time_df.index[-1].date()+timedelta(days=1), freq='1min')
time_df = time_df.reindex(date_add, fill_value=0)
time_df['day'] = time_df.index.day

import matplotlib.pyplot as plt

fig, ax = plt.subplots(figsize=(8,15))
ax.set_yticks(np.arange(0,1500,60))
ax.set_ylim(0,1440)
ax.set_xticks(np.arange(1,25,1))

days = time_df['day'].unique()
for d in days:
    #if d == 1:
    day_df = time_df.query('day == @d')
    colors = [ 'r' if p == 1 else 'g' for p in day_df['present']]
    for i in range(len(day_df)): 
        ax.bar(d, height=1, width=0.5, bottom=i+1, color=colors[i])

plt.show()

【讨论】:

  • 由于一种情况下有到秒的数据,所以数据标准设置为分钟,因此已更正了23:59:59。如果我的回答对你有帮助,请采纳我的回答。
  • 结果确实如我所愿;谢谢!不过,我的笔记本电脑需要大约 15 分钟来创建绘图(必须绘制 24 次 1440 个单独的条)。
猜你喜欢
  • 2021-09-28
  • 1970-01-01
  • 1970-01-01
  • 2021-02-06
  • 2013-01-22
  • 1970-01-01
  • 1970-01-01
  • 2022-01-06
相关资源
最近更新 更多