Skip to content

Commit 7b4d121

Browse files
committed
Add analysis of time-til-first-comment for issues.
1 parent f7c9110 commit 7b4d121

1 file changed

Lines changed: 67 additions & 7 deletions

File tree

site/numpy_issues.md

Lines changed: 67 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -119,9 +119,7 @@ p.yaxis.axis_label = TeX(r"\frac{issues}{day}")
119119
show(p)
120120
```
121121

122-
% TODO: add distribution of labels
123-
124-
### First responders
122+
#### Time to response
125123

126124
```{code-cell} ipython3
127125
---
@@ -135,8 +133,14 @@ newly_created_day_old = [
135133
]
136134
137135
# TODO: really need pandas here
138-
first_commenters = []
139-
for iss in newly_created_day_old:
136+
commented_issues = [
137+
iss for iss in newly_created_day_old
138+
if any(
139+
e["node"]["__typename"] == "IssueComment" for e in iss["timelineItems"]["edges"]
140+
)
141+
]
142+
first_commenters, time_to_first_comment = [], []
143+
for iss in commented_issues:
140144
for e in iss["timelineItems"]["edges"]:
141145
if e["node"]["__typename"] == "IssueComment":
142146
try:
@@ -145,7 +149,26 @@ for iss in newly_created_day_old:
145149
# This can happen e.g. when a user deletes their GH acct
146150
user = "UNKNOWN"
147151
first_commenters.append(user)
152+
dt = np.datetime64(e["node"]["createdAt"]) - np.datetime64(iss["createdAt"])
153+
time_to_first_comment.append(dt.astype("m8[m]"))
148154
break # Only want the first commenter
155+
time_to_first_comment = np.array(time_to_first_comment) # in minutes
156+
157+
median_time_til_first_response = np.median(time_to_first_comment.astype(int) / 60)
158+
159+
cutoffs = [
160+
np.timedelta64(1, "h"),
161+
np.timedelta64(12, "h"),
162+
np.timedelta64(24, "h"),
163+
np.timedelta64(3, "D"),
164+
np.timedelta64(7, "D"),
165+
np.timedelta64(14, "D"),
166+
]
167+
num_issues_commented_by_cutoff = np.array(
168+
[
169+
np.sum(time_to_first_comment < cutoff) for cutoff in cutoffs
170+
]
171+
)
149172
150173
# TODO: Update IssueComment query to include:
151174
# - whether the commenter is a maintainer
@@ -154,16 +177,53 @@ for iss in newly_created_day_old:
154177
# maintainers vs. non-maintainer, and the distribution of how long an issue
155178
# usually sits before it's at least commented on
156179
157-
glue("new_issues_at_least_1_day_old", len(newly_created_day_old))
158180
glue(
159181
"num_new_issues_responded",
160-
percent_val(len(first_commenters), len(newly_created_day_old))
182+
percent_val(len(commented_issues), len(newly_created_day_old))
161183
)
184+
185+
glue("new_issues_at_least_1_day_old", len(newly_created_day_old))
186+
glue("median_response_time", f"{median_time_til_first_response:1.0f}")
162187
```
163188

164189
Of the {glue:text}`new_issues_at_least_1_day_old` issues that are at least 24
165190
hours old, {glue:text}`num_new_issues_responded` of them have been commented
166191
on.
192+
The median time until an issue is first responded to is
193+
{glue:text}`median_response_time` hours.
194+
195+
```{code-cell} ipython3
196+
---
197+
tags: [hide-input]
198+
---
199+
from bokeh.transform import dodge
200+
201+
title = f"Percentage of issues opened since {query_date} that are commented on within..."
202+
203+
x = [str(c) for c in cutoffs]
204+
y = 100 * num_issues_commented_by_cutoff / len(newly_created_day_old)
205+
206+
p = figure(
207+
x_range=x,
208+
y_range=(0, 100),
209+
width=670,
210+
height=400,
211+
title=title,
212+
tooltips=[(r"%", "@top")],
213+
)
214+
p.vbar(x=x, top=y, width=0.8)
215+
p.xaxis.axis_label = "Time interval"
216+
p.yaxis.axis_label = "Percentage of issues commented on within interval"
217+
show(p)
218+
```
219+
220+
#### First responders
221+
222+
```{code-cell} ipython3
223+
---
224+
tags: [hide-input]
225+
---
226+
```
167227

168228
```{code-cell} ipython3
169229
---

0 commit comments

Comments
 (0)