AndreasThinks commited on
Commit
2d97c94
·
verified ·
1 Parent(s): b69f783

fix: filter noise tags (tautological + language duplicates) from all views

Browse files
Files changed (1) hide show
  1. app.py +45 -8
app.py CHANGED
@@ -7,6 +7,36 @@ import os
7
  import logging
8
  from datetime import datetime, timedelta, timezone
9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  # Configure logging
11
  logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s", datefmt="%H:%M:%S")
12
  logger = logging.getLogger("govtech-dashboard")
@@ -79,8 +109,11 @@ def load_filter_options():
79
  languages = pd.read_sql_query(
80
  "SELECT DISTINCT language FROM repositories WHERE language IS NOT NULL AND language != '' ORDER BY language", conn
81
  )["language"].tolist()
 
 
82
  tags = pd.read_sql_query(
83
- "SELECT tag, COUNT(*) as c FROM repository_tags GROUP BY tag ORDER BY c DESC", conn
 
84
  )["tag"].tolist()
85
  orgs = pd.read_sql_query(
86
  "SELECT owner, COUNT(*) as c FROM repositories GROUP BY owner ORDER BY c DESC LIMIT 300", conn
@@ -380,15 +413,17 @@ with tab_tags:
380
 
381
  with col_tl:
382
  st.subheader("Top Tags")
 
 
383
  df_top_tags = query_df(
384
  f"""SELECT rt2.tag, COUNT(DISTINCT r.html_url) as count
385
  FROM repositories r
386
  JOIN repository_tags rt2 ON r.html_url = rt2.html_url
387
  {tag_join_t.replace("rt", "rt_f") if sel_tags else ""}
388
  {where_t.replace("rt.", "rt2.") if where_t else ""}
389
- {"AND" if where_t else "WHERE"} rt2.tag IS NOT NULL
390
- GROUP BY rt2.tag ORDER BY count DESC LIMIT 30""",
391
- params_t,
392
  )
393
  if not df_top_tags.empty:
394
  fig = px.bar(
@@ -690,6 +725,8 @@ with tab_trends:
690
  w_base = (" AND ".join(conds_base)) if conds_base else ""
691
  and_base = ("AND " + w_base) if w_base else ""
692
 
 
 
693
  df_momentum = query_df(
694
  f"""
695
  SELECT
@@ -698,13 +735,13 @@ with tab_trends:
698
  COUNT(DISTINCT CASE WHEN r.created_at >= ? AND r.created_at < ? THEN r.html_url END) as prior
699
  FROM repository_tags rt
700
  JOIN repositories r ON rt.html_url = r.html_url
701
- WHERE r.created_at IS NOT NULL {and_base}
702
  GROUP BY rt.tag
703
  HAVING recent >= 5 AND prior >= 5
704
  ORDER BY (CAST(recent AS FLOAT) / prior) DESC
705
  LIMIT 30
706
  """,
707
- [cutoff_12m, cutoff_24m_str, cutoff_12m] + params_base,
708
  )
709
 
710
  if not df_momentum.empty:
@@ -734,10 +771,10 @@ with tab_trends:
734
  f"""
735
  SELECT rt.tag, COUNT(DISTINCT r.html_url) as recent_count
736
  FROM repository_tags rt JOIN repositories r ON rt.html_url = r.html_url
737
- WHERE r.created_at >= ? {and_base}
738
  GROUP BY rt.tag ORDER BY recent_count DESC LIMIT 20
739
  """,
740
- [cutoff_12m] + params_base,
741
  )
742
  if not df_recent_top.empty:
743
  fig2 = px.bar(
 
7
  import logging
8
  from datetime import datetime, timedelta, timezone
9
 
10
+ # Tags that describe the dataset itself rather than individual repos — excluded from all charts/filters
11
+ BLOCKLIST_TAGS = frozenset([
12
+ "government", "open-source", "public-sector", "open-government",
13
+ "government-software", "government-tool", "government-project",
14
+ "government-repository", "government-platform", "government-code",
15
+ ])
16
+
17
+ # Tags that duplicate the language field already in the schema
18
+ LANGUAGE_TAGS = frozenset([
19
+ "javascript", "python", "java", "typescript", "html", "css", "php",
20
+ "ruby", "shell", "r", "scala", "c#", "kotlin", "go", "rust", "c",
21
+ "c++", "perl", "swift", "matlab", "bash", "json", "xml", "yaml",
22
+ "sql", "makefile",
23
+ ])
24
+
25
+ # Combined filter — tags to hide from dashboard display
26
+ EXCLUDED_TAGS = BLOCKLIST_TAGS | LANGUAGE_TAGS
27
+
28
+ # Minimum repos a tag must appear in to show in charts/filters
29
+ MIN_TAG_REPOS = 2
30
+
31
+ def _tag_filter_sql(tag_col: str = "tag") -> str:
32
+ """Return a SQL fragment excluding noise tags. Use with AND."""
33
+ excluded = EXCLUDED_TAGS
34
+ ph = ",".join(["?"] * len(excluded))
35
+ return f"{tag_col} NOT IN ({ph}) AND {tag_col} IS NOT NULL"
36
+
37
+ def _tag_filter_params() -> list:
38
+ return list(EXCLUDED_TAGS)
39
+
40
  # Configure logging
41
  logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s", datefmt="%H:%M:%S")
42
  logger = logging.getLogger("govtech-dashboard")
 
109
  languages = pd.read_sql_query(
110
  "SELECT DISTINCT language FROM repositories WHERE language IS NOT NULL AND language != '' ORDER BY language", conn
111
  )["language"].tolist()
112
+ tf_sql = _tag_filter_sql()
113
+ tf_params = _tag_filter_params()
114
  tags = pd.read_sql_query(
115
+ f"SELECT tag, COUNT(DISTINCT html_url) as c FROM repository_tags WHERE {tf_sql} GROUP BY tag HAVING c >= {MIN_TAG_REPOS} ORDER BY c DESC",
116
+ conn, params=tf_params
117
  )["tag"].tolist()
118
  orgs = pd.read_sql_query(
119
  "SELECT owner, COUNT(*) as c FROM repositories GROUP BY owner ORDER BY c DESC LIMIT 300", conn
 
413
 
414
  with col_tl:
415
  st.subheader("Top Tags")
416
+ tf_sql_t = _tag_filter_sql("rt2.tag")
417
+ tf_params_t = _tag_filter_params()
418
  df_top_tags = query_df(
419
  f"""SELECT rt2.tag, COUNT(DISTINCT r.html_url) as count
420
  FROM repositories r
421
  JOIN repository_tags rt2 ON r.html_url = rt2.html_url
422
  {tag_join_t.replace("rt", "rt_f") if sel_tags else ""}
423
  {where_t.replace("rt.", "rt2.") if where_t else ""}
424
+ {"AND" if where_t else "WHERE"} {tf_sql_t}
425
+ GROUP BY rt2.tag HAVING count >= {MIN_TAG_REPOS} ORDER BY count DESC LIMIT 30""",
426
+ params_t + tf_params_t,
427
  )
428
  if not df_top_tags.empty:
429
  fig = px.bar(
 
725
  w_base = (" AND ".join(conds_base)) if conds_base else ""
726
  and_base = ("AND " + w_base) if w_base else ""
727
 
728
+ tf_sql_mom = _tag_filter_sql("rt.tag")
729
+ tf_params_mom = _tag_filter_params()
730
  df_momentum = query_df(
731
  f"""
732
  SELECT
 
735
  COUNT(DISTINCT CASE WHEN r.created_at >= ? AND r.created_at < ? THEN r.html_url END) as prior
736
  FROM repository_tags rt
737
  JOIN repositories r ON rt.html_url = r.html_url
738
+ WHERE r.created_at IS NOT NULL AND {tf_sql_mom} {and_base}
739
  GROUP BY rt.tag
740
  HAVING recent >= 5 AND prior >= 5
741
  ORDER BY (CAST(recent AS FLOAT) / prior) DESC
742
  LIMIT 30
743
  """,
744
+ [cutoff_12m, cutoff_24m_str, cutoff_12m] + tf_params_mom + params_base,
745
  )
746
 
747
  if not df_momentum.empty:
 
771
  f"""
772
  SELECT rt.tag, COUNT(DISTINCT r.html_url) as recent_count
773
  FROM repository_tags rt JOIN repositories r ON rt.html_url = r.html_url
774
+ WHERE r.created_at >= ? AND {tf_sql_mom} {and_base}
775
  GROUP BY rt.tag ORDER BY recent_count DESC LIMIT 20
776
  """,
777
+ [cutoff_12m] + tf_params_mom + params_base,
778
  )
779
  if not df_recent_top.empty:
780
  fig2 = px.bar(