Skip to content

Commit

Permalink
[statistics visualize] 折れ線-横軸_日-全体.htmlなどの折れ線グラフに、フェーズごとの作業時間を表示するう…
Browse files Browse the repository at this point in the history
…ようにしました。 (#810)

* プロットする折れ線がない場合に、ファイルを出力しないようにする

* format && lint

* フェーズごとの作業時間をプロットする

* 折れ線グラフの日付が連続になるように配置

* version up

* versionup
  • Loading branch information
yuji38kwmt authored Jul 1, 2022
1 parent a35615c commit 5a67bde
Show file tree
Hide file tree
Showing 7 changed files with 188 additions and 26 deletions.
2 changes: 1 addition & 1 deletion annofabcli/__version__.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = "1.66.2"
__version__ = "1.66.3"
11 changes: 8 additions & 3 deletions annofabcli/statistics/linegraph.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
class LineGraph:
"""
折れ線グラフに対応するクラス
TODO: 引数にx_column, y_columnを受け取るのはよくないかもしれない
"""

def __init__(
Expand Down Expand Up @@ -119,6 +121,9 @@ def config_legend(self) -> None:
折れ線を追加した後に、凡例の位置などを設定します。
"""
fig = self.figure
if len(fig.legend) == 0:
return

fig.legend.location = "top_left"
fig.legend.click_policy = "hide"

Expand All @@ -128,9 +133,9 @@ def config_legend(self) -> None:
fig.legend.label_height = 10
fig.legend.glyph_height = 10

if len(fig.legend) > 0:
legend = fig.legend[0]
fig.add_layout(legend, "left")
# グラフの左側に凡例を表示
legend = fig.legend[0]
fig.add_layout(legend, "left")

def create_button_hiding_all_lines(self) -> Button:
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ def _plot(self, line_graph_list: list[LineGraph], user_id_list: list[str], outpu
# (例) 20000件をプロットする際、この対応がないと、ファイルサイズが3倍以上になる
required_columns = list(set(itertools.chain.from_iterable([e.required_columns for e in line_graph_list])))

line_count = 0
for user_index, user_id in enumerate(user_id_list):
df_subset = df[df[f"first_{self.phase.value}_user_id"] == user_id]
if df_subset.empty:
Expand All @@ -95,9 +96,14 @@ def _plot(self, line_graph_list: list[LineGraph], user_id_list: list[str], outpu
color = get_color_from_palette(user_index)
username = df_subset.iloc[0][f"first_{self.phase.value}_username"]

line_count += 1
for line_graph in line_graph_list:
line_graph.add_line(source, legend_label=username, color=color)

if line_count == 0:
logger.warning(f"プロットするデータがなかっため、'{output_file}'は出力しません。")
return

graph_group_list = []
for line_graph in line_graph_list:
line_graph.config_legend()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,7 @@ def plot_annotation_metrics(

logger.debug(f"{output_file} を出力します。")

line_count = 0
for user_index, user_id in enumerate(user_id_list):
df_subset = df[df["first_annotation_user_id"] == user_id]
if df_subset.empty:
Expand All @@ -309,6 +310,7 @@ def plot_annotation_metrics(
color = get_color_from_palette(user_index)
username = df_subset.iloc[0]["first_annotation_username"]

line_count += 1
for line_graph in line_graph_list:
if line_graph.y_column.endswith(WEEKLY_MOVING_AVERAGE_COLUMN_SUFFIX):
line_graph.add_moving_average_line(
Expand All @@ -324,6 +326,10 @@ def plot_annotation_metrics(
color=color,
)

if line_count == 0:
logger.warning(f"プロットするデータがなかっため、'{output_file}'は出力しません。")
return

self._plot(line_graph_list, output_file)

def plot_input_data_metrics(
Expand Down Expand Up @@ -414,6 +420,8 @@ def plot_input_data_metrics(

logger.debug(f"{output_file} を出力します。")

line_count = 0

for user_index, user_id in enumerate(user_id_list):
df_subset = df[df["first_annotation_user_id"] == user_id]
if df_subset.empty:
Expand All @@ -438,6 +446,7 @@ def plot_input_data_metrics(
color = get_color_from_palette(user_index)
username = df_subset.iloc[0]["first_annotation_username"]

line_count += 1
for line_graph in line_graph_list:
if line_graph.y_column.endswith(WEEKLY_MOVING_AVERAGE_COLUMN_SUFFIX):
line_graph.add_moving_average_line(
Expand All @@ -453,6 +462,10 @@ def plot_input_data_metrics(
color=color,
)

if line_count == 0:
logger.warning(f"プロットするデータがなかっため、'{output_file}'は出力しません。")
return

self._plot(line_graph_list, output_file)

def to_csv(self, output_file: Path) -> None:
Expand Down Expand Up @@ -645,6 +658,7 @@ def plot_annotation_metrics(

logger.debug(f"{output_file} を出力します。")

line_count = 0
for user_index, user_id in enumerate(user_id_list):
df_subset = df[df["first_inspection_user_id"] == user_id]
if df_subset.empty:
Expand Down Expand Up @@ -680,6 +694,10 @@ def plot_annotation_metrics(
color=color,
)

if line_count == 0:
logger.warning(f"プロットするデータがなかっため、'{output_file}'は出力しません。")
return

self._plot(line_graph_list, output_file)

def plot_input_data_metrics(
Expand Down Expand Up @@ -752,6 +770,7 @@ def plot_input_data_metrics(

logger.debug(f"{output_file} を出力します。")

line_count = 0
for user_index, user_id in enumerate(user_id_list):
df_subset = df[df["first_inspection_user_id"] == user_id]
if df_subset.empty:
Expand All @@ -772,6 +791,7 @@ def plot_input_data_metrics(
color = get_color_from_palette(user_index)
username = df_subset.iloc[0]["first_inspection_username"]

line_count += 1
for line_graph in line_graph_list:
if line_graph.y_column.endswith(WEEKLY_MOVING_AVERAGE_COLUMN_SUFFIX):
line_graph.add_moving_average_line(
Expand All @@ -787,6 +807,10 @@ def plot_input_data_metrics(
color=color,
)

if line_count == 0:
logger.warning(f"プロットするデータがなかっため、'{output_file}'は出力しません。")
return

self._plot(line_graph_list, output_file)

def to_csv(self, output_file: Path) -> None:
Expand Down Expand Up @@ -972,6 +996,7 @@ def plot_annotation_metrics(

logger.debug(f"{output_file} を出力します。")

line_count = 0
for user_index, user_id in enumerate(user_id_list):
df_subset = df[df["first_acceptance_user_id"] == user_id]
if df_subset.empty:
Expand All @@ -993,6 +1018,7 @@ def plot_annotation_metrics(
color = get_color_from_palette(user_index)
username = df_subset.iloc[0]["first_acceptance_username"]

line_count += 1
for line_graph in line_graph_list:
if line_graph.y_column.endswith(WEEKLY_MOVING_AVERAGE_COLUMN_SUFFIX):
line_graph.add_moving_average_line(
Expand All @@ -1008,6 +1034,10 @@ def plot_annotation_metrics(
color=color,
)

if line_count == 0:
logger.warning(f"プロットするデータがなかっため、'{output_file}'は出力しません。")
return

self._plot(line_graph_list, output_file)

def plot_input_data_metrics(
Expand Down Expand Up @@ -1079,6 +1109,7 @@ def plot_input_data_metrics(

logger.debug(f"{output_file} を出力します。")

line_count = 0
for user_index, user_id in enumerate(user_id_list):
df_subset = df[df["first_acceptance_user_id"] == user_id]
if df_subset.empty:
Expand All @@ -1099,6 +1130,7 @@ def plot_input_data_metrics(
color = get_color_from_palette(user_index)
username = df_subset.iloc[0]["first_acceptance_username"]

line_count += 1
for line_graph in line_graph_list:
if line_graph.y_column.endswith(WEEKLY_MOVING_AVERAGE_COLUMN_SUFFIX):
line_graph.add_moving_average_line(
Expand All @@ -1114,6 +1146,10 @@ def plot_input_data_metrics(
color=color,
)

if line_count == 0:
logger.warning(f"プロットするデータがなかっため、'{output_file}'は出力しません。")
return

self._plot(line_graph_list, output_file)

def to_csv(self, output_file: Path) -> None:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,15 @@ def add_velocity_columns(df: pandas.DataFrame):
df["monitored_worktime_hour"]
) / get_weekly_sum(df["task_count"])

for column in ["task_count", "input_data_count", "actual_worktime_hour", "monitored_worktime_hour"]:
for column in [
"task_count",
"input_data_count",
"actual_worktime_hour",
"monitored_worktime_hour",
"monitored_annotation_worktime_hour",
"monitored_inspection_worktime_hour",
"monitored_acceptance_worktime_hour",
]:
df[f"{column}{WEEKLY_MOVING_AVERAGE_COLUMN_SUFFIX}"] = get_weekly_moving_average(df[column])

def create_figure(title: str, y_axis_label: str) -> bokeh.plotting.Figure:
Expand Down Expand Up @@ -452,10 +460,7 @@ def create_input_data_figure():
fig_info_list = [
{
"figure": create_figure(title="日ごとの作業時間", y_axis_label="作業時間[hour]"),
"y_info_list": [
{"column": "actual_worktime_hour", "legend": "実績作業時間"},
{"column": "monitored_worktime_hour", "legend": "計測作業時間"},
],
"y_info_list": [{"column": f"{e[0]}_hour", "legend": f"{e[1]}"} for e in phase_prefix],
},
{
"figure": create_figure(title="日ごとのタスクあたり作業時間", y_axis_label="タスクあたり作業時間[hour/task]"),
Expand Down Expand Up @@ -499,9 +504,6 @@ def create_input_data_figure():
"input_data_count",
"actual_worktime_hour",
"monitored_worktime_hour",
"cumsum_task_count",
"cumsum_input_data_count",
"cumsum_actual_worktime_hour",
"actual_worktime_hour/task_count",
"actual_worktime_minute/input_data_count",
"actual_worktime_minute/annotation_count",
Expand Down Expand Up @@ -643,12 +645,72 @@ def create_input_data_figure():

return fig

def create_worktime_figure():
x_column_name = "dt_date"
fig = create_figure(title="日ごとの累積作業時間", y_axis_label="作業時間[hour]")

# 値をプロット
index = 0
plot_line_and_circle(
fig,
x_column_name=x_column_name,
y_column_name="cumsum_actual_worktime_hour",
source=source,
color=get_color_from_small_palette(index),
legend_label="実績作業時間",
)

index += 1
plot_line_and_circle(
fig,
x_column_name=x_column_name,
y_column_name="cumsum_monitored_worktime_hour",
source=source,
color=get_color_from_small_palette(index),
legend_label="計測作業時間",
)

index += 1
plot_line_and_circle(
fig,
x_column_name=x_column_name,
y_column_name="cumsum_monitored_annotation_worktime_hour",
source=source,
color=get_color_from_small_palette(index),
legend_label="計測作業時間(教師付)",
)

index += 1
plot_line_and_circle(
fig,
x_column_name=x_column_name,
y_column_name="cumsum_monitored_inspection_worktime_hour",
source=source,
color=get_color_from_small_palette(index),
legend_label="計測作業時間(検査)",
)

index += 1
plot_line_and_circle(
fig,
x_column_name=x_column_name,
y_column_name="cumsum_monitored_acceptance_worktime_hour",
source=source,
color=get_color_from_small_palette(index),
legend_label="計測作業時間(受入)",
)

return fig

if not self._validate_df_for_output(output_file):
return

df = self.df.copy()
df["dt_date"] = df["date"].map(lambda e: parse(e).date())
df["cumsum_monitored_worktime_hour"] = df["monitored_worktime_hour"].cumsum()

df["cumsum_monitored_annotation_worktime_hour"] = df["monitored_annotation_worktime_hour"].cumsum()
df["cumsum_monitored_inspection_worktime_hour"] = df["monitored_inspection_worktime_hour"].cumsum()
df["cumsum_monitored_acceptance_worktime_hour"] = df["monitored_acceptance_worktime_hour"].cumsum()

logger.debug(f"{output_file} を出力します。")

Expand All @@ -664,10 +726,13 @@ def create_input_data_figure():
"cumsum_input_data_count",
"cumsum_actual_worktime_hour",
"cumsum_monitored_worktime_hour",
"cumsum_monitored_annotation_worktime_hour",
"cumsum_monitored_inspection_worktime_hour",
"cumsum_monitored_acceptance_worktime_hour",
]
hover_tool = create_hover_tool(tooltip_item)

fig_list = [create_task_figure(), create_input_data_figure()]
fig_list = [create_task_figure(), create_input_data_figure(), create_worktime_figure()]

for fig in fig_list:
fig.add_tools(hover_tool)
Expand Down
Loading

0 comments on commit 5a67bde

Please sign in to comment.