首页 > 解决方案 > 有没有办法用 plotly 或 python 创建条形图可视化,其中 y 轴是 24 小时范围,x 轴是所有工作日?

问题描述

我正在尝试创建一组人的工作时间的可视化(最好使用 plotly,因为我想合并一个下拉栏,允许用户在美国的时区之间切换并相应地调整时间)。x 轴是工作日,y 轴是 24 小时范围,条形图会垂直向下(显示某人在周一至周五早上 7 点至下午 3 点工作)并且可以与其他人的工作时间重叠(我知道我需要使用不透明度参数)。

到目前为止,我已经尝试了很多东西,最接近的是以下代码:

import plotly.graph_objects as go
import pandas as pd

# Initialize figure
fig = go.Figure()

week_days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]

# Add Traces
fig.add_trace(
    go.Bar(x=week_days,
           name="Nicole",
           #line=dict(color="#33CFA5")
          ))
#fig.update_yaxes(strftime("%H:%M"))

fig.update_layout(
    updatemenus=[
        dict(
            active=0,
            buttons=list([
                dict(label="None",
                     method="update",
                     args=[{"visible": [True, False, True, False]},
                           {"title": "CSI Work Hours",
                            #"annotations": []
                           }]),
                dict(label="MT",
                     method="update",
                     args=[{"visible": [True, False, False, False]},
                           {"title": "MT",
                            #"annotations": high_annotations
                           }]),
                dict(label="PT",
                     method="update",
                     args=[{"visible": [False, False, True, True]},
                           {"title": "PT",
                            #"annotations": low_annotations
                           }]),
                dict(label="HT",
                     method="update",
                     args=[{"visible": [True, True, True, True]},
                           {"title": "HT",
                            #"annotations": high_annotations + low_annotations
                           }]),
            ]),
        )
    ])

# Set title
fig.update_layout(title_text="CSI")

fig.show()

上述代码的绘图图

#create plot with days of week as x-axis, 24hr range as y-axis
fig, ax = plt.subplots(figsize=(15,15))
#ax.plot_date(start_date, end_date, ydate=True, xdate=False)

#number of days in week 7, set to x-axis to display all week days
l = range(0,7)
week_days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]

# reformat axis ticks to only show hour/min on y-axis; label x-axis w/ week days
from matplotlib.dates import DateFormatter
from matplotlib.axis import Axis
ax.yaxis.set_major_formatter(DateFormatter('%H:%M'))
ax.yaxis.set_major_locator(HourLocator())
ax.invert_yaxis()
#ax.set_yticks(t)
ax.set_xticks(l)
ax.set_xticklabels(week_days)

![上面代码的情节#2][2]

对于实际的数据点,我尝试为每个人或每个时区创建字典,但我不知道如何绘制数据点列表。

person1_hrs_dict = {'Monday' : [7,8,9,10,11,12,13,14,15],
              'Tuesday' : [7,8,9,10,11,12,13,14,15],
              'Wednesday' : [7,8,9,10,11,12,13,14,15],
              'Thursday' : [7,8,9,10,11,12,13,14,15],
              'Friday' : [7,8,9,10,11,12,13,14,15],
              'Saturday' : 0,
              'Sunday' : 0
             }
MT_hrs_dict = {"weekdays":["Monday", "Tuesday", "Wednesday",
 "Thursday", "Friday", "Saturday", "Sunday"],
"csi team": ["person1","person2",etc],
"work hours": []}
#I don't think MT_hrs_dict would work since some people work weekends and have some weekdays off.
#I think I'm overcomplicating it or maybe creating text document might be easier?

这是新的尝试:

employees = list(["Paige","Julissa","Jessica","David","Jamila","Eric Pt",
                 "Nicole","Jackie","Christian","McKay","Eric Pxt","Krissa",
              "Brynn","Jordan","Ethan","Andrew","Tysen","Austin","Dalin",
                "Alex","Pierce","Astha","Spencer","Edgar","Mike","Tiffany"])

df = pd.DataFrame(
    itertools.product(
        pd.date_range("18-oct-2021", periods=7, freq="D").values, employees
    ),
    columns=["date", "employee"],
)

csi_times=["8:00:00.00","11:00:00.00","8:00:00.00","9:00:00.00",
            "10:00:00.00","8:00:00.00","7:00:00.00","9:00:00.00",
            "8:00:00.00","14:30:00.00","9:00:00.00","7:00:00.00",
            "8:00:00.00","9:00:00.00","9:00:00.00","7:00:00.00",
            "22:00:00.00","22:00:00.00","9:00:00.00","15:00:00.00",
            "10:00:00.00","9:00:00.00","8:00:00.00","22:00:00.00",
            "10:00:00.00","7:30:00.00"]
times_format = '%H:%M:%S.%f'
worked_hours = []
n=8
for time in csi_times:
    given_times = datetime.strptime(time, date_format_str)
    final_times = given_times + timedelta(hours=n)
    final_time_strngs = final_times.strftime('%H:%M')
    worked_hours.append(final_time_strngs)
#print(csitimes)

df["start"]=csi_times*7

df["hoursworked"]= worked_hours*7

df["dow"]=df["date"].dt.strftime("%a")

#8,11,8,9,10,8,7,9,8,14,9,7,8,9,9,7,22,22,9,15,10,9,8,22,10,7
#create the figure as bar graph
fig = px.bar(df, x="dow", y="hoursworked", base="start", color="employee", barmode="group",
      labels={
                     "dow": "Days of Week",
                     "hoursworked": "Working Hours",
                     "employee": "CSI Team"
                 },
      title="CSI Working Hours")

#reverse y axis so it starts with 0 (12AM) and goes down to 23(11PM)
fig.update_layout(
   yaxis = dict(autorange = "reversed")
)
fig.show()

新的绘图图

标签: pythonmatplotlibplotplotly

解决方案


  • 做你描述的很简单。已经完成了你所描述的,用星期几、开始、工作时间、员工构建了一个数据框
  • 然后这变成一个简单的条形图,其中dayofweekxaxisyaxis一个条形图,显示开始时间和工作小时数
import itertools
import pandas as pd
import numpy as np
import plotly.express as px

employees = list("ABC")

df = pd.DataFrame(
    itertools.product(
        pd.date_range("18-oct-2021", periods=7, freq="D").values, employees
    ),
    columns=["date", "employee"],
).pipe(
    lambda d: d.assign(
        start=np.random.randint(1, 10, len(d)),
        hoursworked=lambda d: np.random.randint(3, 10, len(d)),
        dow=d["date"].dt.strftime("%a")
    )
)

px.bar(df, x="dow", y="hoursworked", base="start", color="employee", barmode="group")

在此处输入图像描述

数据框样本

日期 员工 开始 工作时间 道琼斯指数
2021-10-18 00:00:00 一个 3 5 星期一
2021-10-18 00:00:00 3 5 星期一
2021-10-18 00:00:00 C 4 4 星期一
2021-10-19 00:00:00 一个 6 6 周二
2021-10-19 00:00:00 1 8 周二
2021-10-19 00:00:00 C 9 5 周二
2021-10-20 00:00:00 一个 7 4 星期三
2021-10-20 00:00:00 2 4 星期三
2021-10-20 00:00:00 C 1 4 星期三
2021-10-21 00:00:00 一个 3 6 星期四

数据框构造 - 更简单的语法

df = pd.DataFrame(
    itertools.product(
        pd.date_range("18-oct-2021", periods=7, freq="D").values, employees
    ),
    columns=["date", "employee"],
)
df["start"] = np.random.randint(1, 10, len(df))
df["hoursworked"] = np.random.randint(3, 10, len(df))
df["dow"] = df["date"].dt.strftime("%a")


推荐阅读