读取 pandas df 中的日期以创建热图分数列表的 Pythonic 方法?
Pythonic method to read dates in a pandas df to create a list of scores for heatmap?
我正在尝试找出一种从 pandas df 生成 'z score' 以用于日历热图中的方法。
Here is an general example of what I'm trying to emulate。它沿 'x' 轴显示星期几,沿 'y' 轴显示星期。每个日期都有一个数值 'z score' 分配给它,创建这个 z 分数是我 运行 遇到麻烦的地方。
我的 df 是从一个 csv 文件创建的,该文件列出了几个不同的任务,其中包含以下列和一些示例数据:
Job,Tool,Start,End
A,Hammer,2020-10-03,2020-11-02
A,Drill,2020-11-05,2020-12-02
A,Hammer,2020-12-03,2020-12-30
此数据适用于甘特图,但需要稍作修改才能用于热图。我已经能够使用 pandas 来生成重要的日期:
def calendarmap():
d1 = min(dff['Start'])
d2 = max(dff['End'])
delta = d2 - d1
dates_that_matter = [d1 + dt.timedelta(i) for i in range(delta.days+1)]
etc
无论使用何种热图方法(sns、go.heatmap 等),我都需要创建一个与所用工具(z 分数)相对应的列表。
fig.add_trace(go.Heatmap(z = z, x = x, y = y)
我想写一个简单的脚本:
- 遍历我的 dates_that_matter
- 检查该日期是否在我的 df 中每一行的开始日期或结束日期之间
- 如果日期存在于我的 df 中,它应该将 z 分数写入对应于每个独特工具的列表。有了这个示例数据,我会对 Hammer = 0.5 和 Drill = 1.0 感到满意。
- 如果日期不存在,则分配的 z 分数应为 0。日期仍会存在,但应反映当天没有工作。
- 容忍不同数量的工具。在此示例中,有 3 个 z 分数状态(0=none、0.5=hammer 和 1.0=drill),但 z 分数状态的数量可能会在 2 到 10 之间波动。
第 2 步和第 5 步是目前对我来说具有挑战性的部分。对此的任何帮助将不胜感激。谢谢。
只回答数据创建。
工艺流程:
- 从原始数据框的每一行创建一个具有开始日期和结束日期的数据框,并将其添加到新数据框。 (创建垂直数据)
- 添加一个工作负载列。
- 按日期汇总工作量
- 添加缺失的日期。 (dfs.reindex())
- 为星期、星期几和月份添加列。
这样就完成了图形数据。
顺便说一句,为了验证,我把它变成了像日历一样的带有月份和日期列的水平格式。
dfs = pd.DataFrame()
for idx, row in df.iterrows():
tmp_date = pd.date_range(row['Start'], row['End'], freq='1D')
tmp_df = pd.DataFrame({'Date':pd.to_datetime(tmp_date), 'Job':row['Job'], 'Tool':row['Tool']})
dfs = dfs.append(tmp_df, ignore_index=True)
dfs['workload'] = dfs['Tool'].apply(lambda x: 1 if x == 'Drill' else 0.5 if x == 'Hammer' else 0.75)
dfs.set_index('Date', inplace=True)
dfs = dfs.groupby(dfs.index)['workload'].sum().to_frame()
dfs = dfs.reindex(pd.date_range(dfs.index.min(), dfs.index.max(), freq='1D',name='Date'), fill_value=0, axis='index')
dfs.reset_index(inplace=True)
import calendar
def getNweek(x):
first_dayofweek = calendar.monthrange(x.year, x.month)[0]
offset = (first_dayofweek - 6) % 7
return (x.day + offset -1) // 7 + 1
dfs['nweek'] = dfs['Date'].apply(lambda x: getNweek(x))
dfs['month'] = dfs['Date'].dt.month
dfs['dayofweek'] = dfs['Date'].dt.dayofweek
dfs.head()
Date workload nweek month dayofweek
0 2020-10-03 0.5 1 10 5
1 2020-10-04 0.5 2 10 6
2 2020-10-05 0.5 2 10 0
3 2020-10-06 0.5 2 10 1
4 2020-10-07 0.5 2 10 2
dfs = dfs.pivot(index='nweek', columns=['month', 'dayofweek'], values='workload')
import itertools
dow = [6,0,1,2,3,4,5]
m = [10,11,12]
new_cols = list(itertools.product(m,dow))
dfs.reindex(new_cols, axis=1)
month 10 11 12
dayofweek 6 0 1 2 3 4 5 6 0 1 ... 3 4 5 6 0 1 2 3 4 5
nweek
1 NaN NaN NaN NaN NaN NaN 0.50 1.25 1.25 0.0 ... 1.0 1.0 1.0 NaN NaN 2.0 2.0 0.5 0.5 0.5
2 0.50 0.50 0.50 0.50 0.50 0.50 0.50 1.00 1.00 1.0 ... 1.0 1.0 1.0 0.5 0.5 0.5 0.5 0.5 0.5 0.5
3 0.50 0.50 0.50 0.50 0.50 0.50 0.50 1.00 1.00 1.0 ... 1.0 1.0 1.0 0.5 0.5 0.5 0.5 0.5 0.5 0.5
4 0.50 0.50 0.50 0.50 0.50 1.25 1.25 1.00 1.00 1.0 ... 2.0 2.0 2.0 0.5 0.5 0.5 1.0 1.0 1.0 1.0
5 1.25 1.25 1.25 1.25 1.25 1.25 1.25 2.00 2.00 NaN ... NaN NaN NaN 1.0 1.0 1.0 1.0 NaN NaN NaN
我正在尝试找出一种从 pandas df 生成 'z score' 以用于日历热图中的方法。
Here is an general example of what I'm trying to emulate。它沿 'x' 轴显示星期几,沿 'y' 轴显示星期。每个日期都有一个数值 'z score' 分配给它,创建这个 z 分数是我 运行 遇到麻烦的地方。
我的 df 是从一个 csv 文件创建的,该文件列出了几个不同的任务,其中包含以下列和一些示例数据:
Job,Tool,Start,End
A,Hammer,2020-10-03,2020-11-02
A,Drill,2020-11-05,2020-12-02
A,Hammer,2020-12-03,2020-12-30
此数据适用于甘特图,但需要稍作修改才能用于热图。我已经能够使用 pandas 来生成重要的日期:
def calendarmap():
d1 = min(dff['Start'])
d2 = max(dff['End'])
delta = d2 - d1
dates_that_matter = [d1 + dt.timedelta(i) for i in range(delta.days+1)]
etc
无论使用何种热图方法(sns、go.heatmap 等),我都需要创建一个与所用工具(z 分数)相对应的列表。
fig.add_trace(go.Heatmap(z = z, x = x, y = y)
我想写一个简单的脚本:
- 遍历我的 dates_that_matter
- 检查该日期是否在我的 df 中每一行的开始日期或结束日期之间
- 如果日期存在于我的 df 中,它应该将 z 分数写入对应于每个独特工具的列表。有了这个示例数据,我会对 Hammer = 0.5 和 Drill = 1.0 感到满意。
- 如果日期不存在,则分配的 z 分数应为 0。日期仍会存在,但应反映当天没有工作。
- 容忍不同数量的工具。在此示例中,有 3 个 z 分数状态(0=none、0.5=hammer 和 1.0=drill),但 z 分数状态的数量可能会在 2 到 10 之间波动。
第 2 步和第 5 步是目前对我来说具有挑战性的部分。对此的任何帮助将不胜感激。谢谢。
只回答数据创建。 工艺流程:
- 从原始数据框的每一行创建一个具有开始日期和结束日期的数据框,并将其添加到新数据框。 (创建垂直数据)
- 添加一个工作负载列。
- 按日期汇总工作量
- 添加缺失的日期。 (dfs.reindex())
- 为星期、星期几和月份添加列。 这样就完成了图形数据。 顺便说一句,为了验证,我把它变成了像日历一样的带有月份和日期列的水平格式。
dfs = pd.DataFrame()
for idx, row in df.iterrows():
tmp_date = pd.date_range(row['Start'], row['End'], freq='1D')
tmp_df = pd.DataFrame({'Date':pd.to_datetime(tmp_date), 'Job':row['Job'], 'Tool':row['Tool']})
dfs = dfs.append(tmp_df, ignore_index=True)
dfs['workload'] = dfs['Tool'].apply(lambda x: 1 if x == 'Drill' else 0.5 if x == 'Hammer' else 0.75)
dfs.set_index('Date', inplace=True)
dfs = dfs.groupby(dfs.index)['workload'].sum().to_frame()
dfs = dfs.reindex(pd.date_range(dfs.index.min(), dfs.index.max(), freq='1D',name='Date'), fill_value=0, axis='index')
dfs.reset_index(inplace=True)
import calendar
def getNweek(x):
first_dayofweek = calendar.monthrange(x.year, x.month)[0]
offset = (first_dayofweek - 6) % 7
return (x.day + offset -1) // 7 + 1
dfs['nweek'] = dfs['Date'].apply(lambda x: getNweek(x))
dfs['month'] = dfs['Date'].dt.month
dfs['dayofweek'] = dfs['Date'].dt.dayofweek
dfs.head()
Date workload nweek month dayofweek
0 2020-10-03 0.5 1 10 5
1 2020-10-04 0.5 2 10 6
2 2020-10-05 0.5 2 10 0
3 2020-10-06 0.5 2 10 1
4 2020-10-07 0.5 2 10 2
dfs = dfs.pivot(index='nweek', columns=['month', 'dayofweek'], values='workload')
import itertools
dow = [6,0,1,2,3,4,5]
m = [10,11,12]
new_cols = list(itertools.product(m,dow))
dfs.reindex(new_cols, axis=1)
month 10 11 12
dayofweek 6 0 1 2 3 4 5 6 0 1 ... 3 4 5 6 0 1 2 3 4 5
nweek
1 NaN NaN NaN NaN NaN NaN 0.50 1.25 1.25 0.0 ... 1.0 1.0 1.0 NaN NaN 2.0 2.0 0.5 0.5 0.5
2 0.50 0.50 0.50 0.50 0.50 0.50 0.50 1.00 1.00 1.0 ... 1.0 1.0 1.0 0.5 0.5 0.5 0.5 0.5 0.5 0.5
3 0.50 0.50 0.50 0.50 0.50 0.50 0.50 1.00 1.00 1.0 ... 1.0 1.0 1.0 0.5 0.5 0.5 0.5 0.5 0.5 0.5
4 0.50 0.50 0.50 0.50 0.50 1.25 1.25 1.00 1.00 1.0 ... 2.0 2.0 2.0 0.5 0.5 0.5 1.0 1.0 1.0 1.0
5 1.25 1.25 1.25 1.25 1.25 1.25 1.25 2.00 2.00 NaN ... NaN NaN NaN 1.0 1.0 1.0 1.0 NaN NaN NaN