Skip to content

Commit ae7e693

Browse files
authored
enh: create package metric dashboard (#119)
* enh: create package metric dashboard * fixes
1 parent f43a287 commit ae7e693

File tree

4 files changed

+295
-0
lines changed

4 files changed

+295
-0
lines changed

_quarto.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,16 @@ website:
3030
href: peer-review/review-trends.qmd
3131
- text: Accepted Package Metrics
3232
href: peer-review/accepted-packages.qmd
33+
- text: Package Dashboard
34+
href: peer-review/pyos-package-dashboard.qmd
3335
- text: "Contributors"
3436
menu:
3537
- text: Contributor Data
3638
href: contributors/contributors.qmd
3739
- text: Sprint Data
3840
href: contributors/sprints.qmd
3941

42+
4043
right:
4144
- icon: github
4245
href: https://github.com/pyopensci/metrics

peer-review/accepted-packages.qmd

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,10 @@ package_df['open_issues_count'] = package_df['gh_meta'].apply(
122122
```
123123

124124
```{python}
125+
# Extract "open_issues_count" value from the 'gh_meta' column
126+
package_df['open_issues_count'] = package_df['gh_meta'].apply(
127+
lambda x: x.get('open_issues_count') if isinstance(x, dict) else None
128+
)
125129
# Render a graph plot of open issue count
126130
chart = (
127131
alt.Chart(package_df).mark_bar(color="#735fab")
Lines changed: 287 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,287 @@
1+
---
2+
title: "pyOpenSci Accepted Package Metrics"
3+
format:
4+
dashboard:
5+
scrolling: true
6+
execute:
7+
echo: false
8+
---
9+
10+
## Row {height=0%}
11+
12+
```{python}
13+
#| echo: false
14+
import ast
15+
import warnings
16+
from itables import show
17+
from pathlib import Path
18+
19+
import altair as alt
20+
import pandas as pd
21+
import plotly.express as px
22+
23+
# This is a local module that stores the plot theme
24+
from pyosmetrics.plot_theme import load_poppins_font, register_and_enable_poppins_theme
25+
26+
pd.options.mode.chained_assignment = None
27+
pd.options.future.infer_string = True
28+
29+
warnings.filterwarnings("ignore")
30+
31+
# Load the & register Poppins theme
32+
load_poppins_font()
33+
register_and_enable_poppins_theme()
34+
35+
package_data_path = Path.cwd().parents[0] / "_data" / "package_data.csv"
36+
package_df = pd.read_csv(package_data_path)
37+
38+
# Parse the "gh_meta" column back into dictionaries
39+
package_df['gh_meta'] = package_df['gh_meta'].apply(
40+
lambda x: ast.literal_eval(x) if isinstance(x, str) else x
41+
)
42+
# Extract "forks_count" value from the 'gh_meta' column
43+
package_df['forks_count'] = package_df['gh_meta'].apply(
44+
lambda x: x.get('forks_count'
45+
) if isinstance(x, dict) else None
46+
)
47+
48+
package_df['contrib_count'] = package_df['gh_meta'].apply(
49+
lambda x: x.get('contrib_count') if isinstance(x, dict) else None
50+
)
51+
average_contribs = int(package_df['contrib_count'].mean())
52+
53+
average_forks = int(package_df['forks_count'].mean())
54+
55+
```
56+
57+
## Row {height=5%}
58+
59+
```{python}
60+
#| content: valuebox
61+
#| title: "Total Accepted Packages"
62+
63+
total = len(package_df)
64+
65+
dict(
66+
icon = "box2-heart",
67+
color = "primary",
68+
value = total
69+
)
70+
```
71+
72+
```{python}
73+
#| content: valuebox
74+
#| title: "Average Contributors Across Packages"
75+
# fails if the value isn't an int
76+
dict(
77+
icon = "person-hearts",
78+
color = "primary",
79+
value = average_contribs
80+
)
81+
```
82+
83+
84+
```{python}
85+
#| content: valuebox
86+
#| title: "Average Forks"
87+
# fails if the value isn't an int
88+
dict(
89+
icon = "copy",
90+
color = "primary",
91+
value = average_forks
92+
)
93+
```
94+
## Row {height=10%}
95+
96+
```{python}
97+
#| title: Distribution of Forks Across Packages
98+
99+
fig = px.violin(
100+
package_df,
101+
y='forks_count',
102+
color_discrete_sequence=['#81c0aa'],
103+
title = 'Distribution of forks across packages'
104+
)
105+
106+
fig = fig.update_layout(
107+
yaxis_title='Fork count',
108+
title_x=0.5,
109+
)
110+
111+
fig
112+
```
113+
114+
115+
```{python}
116+
#| title: Total Package Forks
117+
118+
fig = px.bar(
119+
package_df.sort_values('forks_count', ascending=False),
120+
x='package_name',
121+
y='forks_count',
122+
title='Number of forks per repository',
123+
labels={'package_name': 'Package name', 'forks_count': 'Fork count'},
124+
color_discrete_sequence=['#81c0aa']
125+
)
126+
127+
fig = fig.update_layout(
128+
xaxis_tickangle=45,
129+
xaxis_title='Package name',
130+
yaxis_title='Fork count',
131+
title_x=0.5, # center title
132+
legend_orientation='h',
133+
)
134+
135+
fig
136+
```
137+
138+
## Row {height=10%}
139+
140+
```{python}
141+
#| echo: false
142+
143+
```
144+
145+
```{python}
146+
fig = px.violin(
147+
package_df,
148+
y='contrib_count',
149+
box=True,
150+
color_discrete_sequence=['#735fab'],
151+
title='Distribution of contributors across packages'
152+
)
153+
154+
fig = fig.update_layout(
155+
yaxis_title='Contributor count',
156+
title_x=0.5,
157+
height=500,
158+
margin=dict(t=50, b=50, l=50, r=50)
159+
)
160+
161+
fig
162+
163+
```
164+
165+
166+
```{python}
167+
# Contributor count
168+
fig = px.bar(
169+
package_df.sort_values('contrib_count', ascending=False),
170+
x='package_name',
171+
y='contrib_count',
172+
title='Number of contributors per repository',
173+
labels={'package_name': 'Package name', 'contrib_count': 'Contributor count'},
174+
color_discrete_sequence=['#735fab'] # match your Altair color
175+
)
176+
177+
# Format layout
178+
fig=fig.update_layout(
179+
xaxis_tickangle=45,
180+
xaxis_title='Package name',
181+
yaxis_title='Contributor count',
182+
title_x=0.5,
183+
legend_orientation='h',
184+
height=500
185+
)
186+
187+
fig
188+
```
189+
190+
191+
## Row {height=10%}
192+
193+
```{python}
194+
#| echo: false
195+
# Extract "open_issues_count" value from the 'gh_meta' column
196+
package_df['open_issues_count'] = package_df['gh_meta'].apply(
197+
lambda x: x.get('open_issues_count') if isinstance(x, dict) else None
198+
)
199+
200+
# Violin plot
201+
fig_violin = px.violin(
202+
package_df,
203+
y="open_issues_count",
204+
box=True,
205+
title="Distribution of open issues across repositories"
206+
)
207+
208+
fig_violin.show()
209+
210+
```
211+
212+
```{python}
213+
# Bar plot
214+
fig_bar = px.bar(
215+
package_df.sort_values("open_issues_count", ascending=False),
216+
x="package_name",
217+
y="open_issues_count",
218+
title="Number of open issues per repository",
219+
labels={
220+
"package_name": "Package name",
221+
"open_issues_count": "Open issues count"
222+
}
223+
)
224+
225+
# Update x-axis for angled labels
226+
fig_bar=fig_bar.update_layout(
227+
xaxis_tickangle=45,
228+
bargap=0.2, # optional, for spacing
229+
xaxis_title="Package name",
230+
yaxis_title="Open issues count",
231+
legend=dict(orientation="h", yanchor="bottom", y=1.02, xanchor="center", x=0.5)
232+
)
233+
234+
fig_bar.show()
235+
```
236+
237+
238+
239+
## Row {height=10%}
240+
241+
```{python}
242+
#| echo: false
243+
#|
244+
# Extract "stargazers_count" value from the 'gh_meta' column
245+
package_df['stargazers_count'] = package_df['gh_meta'].apply(
246+
lambda x: x.get('stargazers_count') if isinstance(x, dict) else None
247+
)
248+
249+
fig_violin_stars = px.violin(
250+
package_df,
251+
y="stargazers_count",
252+
box=True,
253+
title="Distribution of stargazers across repositories"
254+
)
255+
256+
fig_violin_stars=fig_violin_stars.update_layout(
257+
yaxis_title="Stargazer count"
258+
)
259+
260+
fig_violin_stars.show()
261+
262+
```
263+
264+
```{python}
265+
# Bar chart - stargazers
266+
fig_bar_stars = px.bar(
267+
package_df.sort_values("stargazers_count", ascending=False),
268+
x="package_name",
269+
y="stargazers_count",
270+
title="Number of stargazers per repository",
271+
labels={
272+
"package_name": "Package name",
273+
"stargazers_count": "Stargazer count"
274+
}
275+
)
276+
277+
# Adjust x-axis for angled labels
278+
fig_bar_stars=fig_bar_stars.update_layout(
279+
xaxis_tickangle=45,
280+
bargap=0.2,
281+
xaxis_title="Package name",
282+
yaxis_title="Stargazer count",
283+
legend=dict(orientation="h", yanchor="bottom", y=1.02, xanchor="center", x=0.5)
284+
)
285+
286+
fig_bar_stars.show()
287+
```

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ itables # interactive tables!
88
tqdm
99
nox
1010
pygithub # for github API
11+
plotly

0 commit comments

Comments
 (0)