Bearloga has uploaded a new change for review. ( 
https://gerrit.wikimedia.org/r/379150 )

Change subject: [WIP] Add maplink & mapframe prevalence graphs and modularize
......................................................................

[WIP] Add maplink & mapframe prevalence graphs and modularize

- Splits up server.R into modules (like Search & Portal dashboards)
- Adds maplink & mapframe prevalence graphs
  - Overall prevalence
  - Language-project breakdown of prevalence

Bug: T170022
Change-Id: If1f1efa619037ce8adea873c148f9a1f78376506
---
M CHANGELOG.md
A modules/feature_usage.R
A modules/geographic_breakdown.R
A modules/kartographer/language-project_breakdown.R
A modules/kartographer/overall_prevalence.R
A modules/kartotherian.R
M server.R
A tab_documentation/overall_prevalence.md
A tab_documentation/prevalence_langproj.md
M tab_documentation/tiles_summary.md
M ui.R
M utils.R
12 files changed, 536 insertions(+), 161 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/wikimedia/discovery/wetzel 
refs/changes/50/379150/1

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 208e2ab..f3e77ee 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,10 @@
 # Change Log (Patch Notes)
 All notable changes to this project will be documented in this file.
 
+## 2017/09/18
+- Modularized the dashboard source code
+- Added maplink & mapframe prevalence graphs 
([T170022](https://phabricator.wikimedia.org/T170022))
+
 ## 2017/06/20
 - Added licensing info ([T167930](https://phabricator.wikimedia.org/T167930))
 
diff --git a/modules/feature_usage.R b/modules/feature_usage.R
new file mode 100644
index 0000000..ec2460e
--- /dev/null
+++ b/modules/feature_usage.R
@@ -0,0 +1,55 @@
+output$users_per_platform <- renderDygraph({
+  user_data %>%
+    polloi::smoother(smooth_level = 
polloi::smooth_switch(input$smoothing_global, 
input$smoothing_users_per_platform)) %>%
+    polloi::make_dygraph("Date", "Events", "Unique users by platform, by day") 
%>%
+    dyAxis("y", logscale = input$users_per_platform_logscale) %>%
+    dyLegend(labelsDiv = "users_per_platform_legend", show = "always") %>%
+    dyRangeSelector %>%
+    dyEvent(as.Date("2016-04-15"), "A (Maps EL bug)", labelLoc = "bottom") %>%
+    dyEvent(as.Date("2016-06-17"), "A (Maps EL patch)", labelLoc = "bottom") 
%>%
+    dyEvent(as.Date("2017-01-01"), "R (reportupdater)", labelLoc = "bottom")
+})
+
+output$geohack_feature_usage <- renderDygraph({
+  usage_data$GeoHack %>%
+    polloi::smoother(smooth_level = 
polloi::smooth_switch(input$smoothing_global, 
input$smoothing_geohack_feature_usage)) %>%
+    polloi::make_dygraph("Date", "Events", "Feature usage for GeoHack") %>%
+    dyRangeSelector %>%
+    dyAxis("y", logscale = input$geohack_feature_usage_logscale) %>%
+    dyEvent(as.Date("2016-04-15"), "A (Maps EL bug)", labelLoc = "bottom") %>%
+    dyEvent(as.Date("2016-06-17"), "A (Maps EL patch)", labelLoc = "bottom") 
%>%
+    dyEvent(as.Date("2017-01-01"), "R (reportupdater)", labelLoc = "bottom")
+})
+
+output$wikiminiatlas_feature_usage <- renderDygraph({
+  usage_data$WikiMiniAtlas %>%
+    polloi::smoother(smooth_level = 
polloi::smooth_switch(input$smoothing_global, 
input$smoothing_wikiminiatlas_feature_usage)) %>%
+    polloi::make_dygraph("Date", "Events", "Feature usage for WikiMiniAtlas") 
%>%
+    dyRangeSelector %>%
+    dyAxis("y", logscale = input$wikiminiatlas_feature_usage_logscale) %>%
+    dyEvent(as.Date("2016-04-15"), "A (Maps EL bug)", labelLoc = "bottom") %>%
+    dyEvent(as.Date("2016-06-17"), "A (Maps EL patch)", labelLoc = "bottom") 
%>%
+    dyEvent(as.Date("2017-01-01"), "R (reportupdater)", labelLoc = "bottom")
+})
+
+output$wikivoyage_feature_usage <- renderDygraph({
+  usage_data$Wikivoyage %>%
+    polloi::smoother(smooth_level = 
polloi::smooth_switch(input$smoothing_global, 
input$smoothing_wikivoyage_feature_usage)) %>%
+    polloi::make_dygraph("Date", "Events", "Feature usage for Wikivoyage") %>%
+    dyRangeSelector %>%
+    dyAxis("y", logscale = input$wikivoyage_feature_usage_logscale) %>%
+    dyEvent(as.Date("2016-04-15"), "A (Maps EL bug)", labelLoc = "bottom") %>%
+    dyEvent(as.Date("2016-06-17"), "A (Maps EL patch)", labelLoc = "bottom") 
%>%
+    dyEvent(as.Date("2017-01-01"), "R (reportupdater)", labelLoc = "bottom")
+})
+
+output$wiwosm_feature_usage <- renderDygraph({
+  usage_data$WIWOSM %>%
+    polloi::smoother(smooth_level = 
polloi::smooth_switch(input$smoothing_global, 
input$smoothing_wiwosm_feature_usage)) %>%
+    polloi::make_dygraph("Date", "Events", "Feature usage for WIWOSM") %>%
+    dyRangeSelector %>%
+    dyAxis("y", logscale = input$wiwosm_feature_usage_logscale) %>%
+    dyEvent(as.Date("2016-04-15"), "A (Maps EL bug)", labelLoc = "bottom") %>%
+    dyEvent(as.Date("2016-06-17"), "A (Maps EL patch)", labelLoc = "bottom") 
%>%
+    dyEvent(as.Date("2017-01-01"), "R (reportupdater)", labelLoc = "bottom")
+})
diff --git a/modules/geographic_breakdown.R b/modules/geographic_breakdown.R
new file mode 100644
index 0000000..99deca5
--- /dev/null
+++ b/modules/geographic_breakdown.R
@@ -0,0 +1,7 @@
+output$users_by_country <- renderDygraph({
+  country_data %>%
+    polloi::smoother(smooth_level = 
polloi::smooth_switch(input$smoothing_global, 
input$smoothing_users_by_country)) %>%
+    polloi::make_dygraph("Date", "Users (%)", "Geographic breakdown of maps 
users") %>%
+    dyRangeSelector(fillColor = "", strokeColor = "") %>%
+    dyEvent(as.Date("2017-01-01"), "R (reportupdater)", labelLoc = "bottom")
+})
diff --git a/modules/kartographer/language-project_breakdown.R 
b/modules/kartographer/language-project_breakdown.R
new file mode 100644
index 0000000..ec9bbf6
--- /dev/null
+++ b/modules/kartographer/language-project_breakdown.R
@@ -0,0 +1,147 @@
+# TODO: select "(None)" in languages if user selects "Wikimedia Commons"
+
+output$language_selector_container <- renderUI({
+  temp_language <- available_languages
+  if ("Maplink" %in% input$prevalence_langproj_feature) {
+    temp_language <- temp_language[temp_language$maplink, ]
+  }
+  if ("Mapframe" %in% input$prevalence_langproj_feature) {
+    temp_language <- temp_language[temp_language$mapframe, ]
+  }
+
+  if (input$language_order == "alphabet") {
+    languages_to_display <- sort(temp_language$language)
+  } else {
+    languages_to_display <- 
temp_language$language[order(temp_language$articles, decreasing = TRUE)]
+  }
+
+  if (!is.null(input$language_selector)) {
+    selected_language <- input$language_selector
+  } else {
+    selected_language <- languages_to_display[1]
+  }
+
+  return(selectInput(
+    "language_selector", "Language",
+    multiple = TRUE, selectize = FALSE, size = 19,
+    choices = languages_to_display, selected = selected_language
+  ))
+})
+
+output$project_selector_container <- renderUI({
+  req(input$language_selector)
+  temp_project <- available_projects
+  if ("Maplink" %in% input$prevalence_langproj_feature) {
+    temp_project <- temp_project[temp_project$maplink, ]
+  }
+  if ("Mapframe" %in% input$prevalence_langproj_feature) {
+    temp_project <- temp_project[temp_project$mapframe, ]
+  }
+
+  if (input$project_order == "alphabet") {
+    projects_to_display <- sort(temp_project$project)
+  } else {
+    projects_to_display <- temp_project$project[order(temp_project$articles, 
decreasing = TRUE)]
+  }
+
+  if (!is.null(input$project_selector)) {
+    selected_project <- input$project_selector
+  } else {
+    selected_project <- projects_to_display[1]
+  }
+
+  return(selectInput(
+    "project_selector", "Project",
+    multiple = TRUE, selectize = FALSE, size = 19,
+    choices = projects_to_display, selected = selected_project
+  ))
+})
+
+output$prevalence_langproj_plot <- renderDygraph({
+  req(input$language_selector, input$project_selector, 
input$prevalence_langproj_feature)
+
+  if (length(input$prevalence_langproj_feature) == 1) {
+    if ("Maplink" %in% input$prevalence_langproj_feature) {
+      feature_prevalence <- maplink_prevalence %>%
+        dplyr::mutate(feature_articles = maplink_articles)
+    } else {
+      feature_prevalence <- mapframe_prevalence %>%
+        dplyr::mutate(feature_articles = mapframe_articles)
+    }
+    if (input$prevalence_langproj_filter) {
+      feature_prevalence <- feature_prevalence %>%
+        dplyr::filter(feature_articles > 0)
+    }
+    if (length(input$language_selector) == 1 && input$language_selector[1] == 
"(None)") {
+      feature_prevalence <- feature_prevalence %>%
+        dplyr::group_by(date, key = project) %>%
+        dplyr::summarize(value = round(100 * sum(feature_articles) / 
sum(total_articles), 2)) %>%
+        dplyr::ungroup() %>%
+        tidyr::spread(key, value)
+    } else {
+      feature_prevalence <- feature_prevalence %>%
+        dplyr::mutate(
+          label = paste0(dplyr::if_else(is.na(language), "", paste0(language, 
" ")), project),
+          language = dplyr::if_else(is.na(language), "(None)", language)
+        ) %>%
+        dplyr::filter(language %in% input$language_selector, project %in% 
input$project_selector) %>%
+        dplyr::group_by(date, key = label) %>%
+        dplyr::summarize(value = round(100 * sum(feature_articles) / 
sum(total_articles), 2)) %>%
+        dplyr::ungroup() %>%
+        tidyr::spread(key, value)
+    }
+  } else {
+    feature_prevalence <- dplyr::inner_join(
+      maplink_prevalence,
+      mapframe_prevalence,
+      by = c("date", "wiki", "project", "language")
+    ) %>%
+      dplyr::filter(project %in% input$project_selector)
+    if (input$prevalence_langproj_filter) {
+      feature_prevalence <- feature_prevalence %>%
+        dplyr::filter(maplink_articles > 0, mapframe_articles > 0)
+    }
+    if (length(input$language_selector) == 1 && input$language_selector[1] == 
"(None)") {
+      feature_prevalence <- feature_prevalence %>%
+        dplyr::group_by(date, label = project) %>%
+        dplyr::summarize(
+          Maplink = round(100 * sum(maplink_articles) / sum(total_articles.x), 
2),
+          Mapframe = round(100 * sum(mapframe_articles) / 
sum(total_articles.y), 2)
+        ) %>%
+        dplyr::ungroup() %>%
+        tidyr::gather(feature, prevalence, -c(date, label)) %>%
+        dplyr::transmute(
+          date = date, value = prevalence,
+          key = paste0(feature, " (", label, ")")
+        ) %>%
+        tidyr::spread(key, value)
+    } else {
+      feature_prevalence <- feature_prevalence %>%
+        dplyr::mutate(
+          label = paste0(dplyr::if_else(is.na(language), "", paste0(language, 
" ")), project),
+          language = dplyr::if_else(is.na(language), "(None)", language)
+        ) %>%
+        dplyr::filter(language %in% input$language_selector, project %in% 
input$project_selector) %>%
+        dplyr::group_by(date, label) %>%
+        dplyr::summarize(
+          Maplink = round(100 * sum(maplink_articles) / sum(total_articles.x), 
2),
+          Mapframe = round(100 * sum(mapframe_articles) / 
sum(total_articles.y), 2)
+        ) %>%
+        dplyr::ungroup() %>%
+        tidyr::gather(feature, prevalence, -c(date, label)) %>%
+        dplyr::transmute(
+          date = date, value = prevalence,
+          key = paste0(feature, " (", label, ")")
+        ) %>%
+        tidyr::spread(key, value)
+    }
+  }
+  feature_prevalence %>%
+    polloi::smoother(smooth_level = 
polloi::smooth_switch(input$smoothing_global, 
input$smoothing_prevalence_langproj), rename = FALSE) %>%
+    polloi::reorder_columns() %>%
+    polloi::make_dygraph(
+      "Date", "Prevalence (%)",
+      paste(paste(input$prevalence_langproj_feature, collapse = " and "), 
"prevalence")
+    ) %>%
+    dyLegend(show = "always", width = 400, labelsDiv = 
"prevalence_langproj_legend")
+})
diff --git a/modules/kartographer/overall_prevalence.R 
b/modules/kartographer/overall_prevalence.R
new file mode 100644
index 0000000..4e5034f
--- /dev/null
+++ b/modules/kartographer/overall_prevalence.R
@@ -0,0 +1,6 @@
+output$overall_prevalence_series <- renderDygraph({
+  prevalence %>%
+    polloi::reorder_columns() %>%
+    polloi::make_dygraph("Date", "Prevalence (%)", "Maplink and mapframe 
prevalence on Wikimedia projects") %>%
+    dyLegend(labelsDiv = "overall_prevalence_series_legend", show = "always")
+})
diff --git a/modules/kartotherian.R b/modules/kartotherian.R
new file mode 100644
index 0000000..ead8141
--- /dev/null
+++ b/modules/kartotherian.R
@@ -0,0 +1,88 @@
+output$tiles_summary_series <- renderDygraph({
+  temp <- polloi::data_select(input$tile_summary_automata_check, 
new_tiles_automata, new_tiles_no_automata)[, list(
+    `total tiles` = sum(total),
+    `total users` = sum(users),
+    `average tiles per user` = sum(total)/sum(users)
+  ), by = "date"]
+  switch(input$tiles_summary_variable,
+         Users = { temp %<>% dplyr::select(-`total tiles`) },
+         Tiles = { temp %<>% dplyr::select(-`total users`) })
+  temp %<>% polloi::smoother(smooth_level = 
polloi::smooth_switch(input$smoothing_global, 
input$smoothing_tiles_summary_series))
+  polloi::make_dygraph(temp, "Date", input$tiles_summary_variable, "Tile 
usage") %>%
+    dySeries(name = grep('average tiles per user', names(temp), value = TRUE), 
axis = 'y2') %>%
+    dyAxis(name = 'y', drawGrid = FALSE, logscale = 
input$tiles_summary_logscale) %>%
+    dyAxis(name = 'y2', independentTicks = TRUE, drawGrid = FALSE) %>%
+    dyLegend(labelsDiv = "tiles_summary_series_legend", show = "always") %>%
+    dyRangeSelector(retainDateWindow = TRUE) %>%
+    dyEvent(as.Date("2015-09-17"), "A (announcement)", labelLoc = "bottom") %>%
+    dyEvent(as.Date("2016-01-08"), "B (enwiki launch)", labelLoc = "bottom") 
%>%
+    dyEvent(as.Date("2016-01-12"), "C (cache clear)", labelLoc = "bottom") %>%
+    dyEvent(as.Date("2016-11-09"), "D (pkget)", labelLoc = "bottom") %>%
+    dyEvent(as.Date("2017-01-01"), "R (reportupdater)", labelLoc = "bottom") 
%>%
+    dyEvent(as.Date("2017-08-14"), "E (pkget)", labelLoc = "bottom")
+})
+
+output$tiles_style_series <- renderDygraph({
+  polloi::data_select(
+    input$tile_style_automata_check,
+    new_tiles_automata,
+    new_tiles_no_automata
+  )[, j = list(`total tiles` = sum(total)),
+    by = c("date", "style")] %>%
+    tidyr::spread(style, `total tiles`, fill = 0) %>%
+    polloi::smoother(smooth_level = 
polloi::smooth_switch(input$smoothing_global, 
input$smoothing_tiles_style_series)) %>%
+    polloi::make_dygraph("Date", "Tiles", "Total tiles by style", legend_name 
= "Style") %>%
+    dyAxis("y", logscale = input$tiles_style_logscale) %>%
+    dyLegend(labelsDiv = "tiles_style_series_legend", show = "always") %>%
+    dyRangeSelector %>%
+    dyEvent(as.Date("2015-09-17"), "A (announcement)", labelLoc = "bottom") %>%
+    dyEvent(as.Date("2016-01-08"), "B (enwiki launch)", labelLoc = "bottom") 
%>%
+    dyEvent(as.Date("2016-01-12"), "C (cache clear)", labelLoc = "bottom") %>%
+    dyEvent(as.Date("2016-11-09"), "D (pkget)", labelLoc = "top") %>%
+    dyEvent(as.Date("2017-01-01"), "R (reportupdater)", labelLoc = "bottom") 
%>%
+    dyEvent(as.Date("2017-08-14"), "E (pkget)", labelLoc = "bottom")
+})
+
+output$tiles_users_series <- renderDygraph({
+  polloi::data_select(
+    input$tile_users_automata_check,
+    new_tiles_automata,
+    new_tiles_no_automata
+  )[, j = list(`total users` = sum(users)),
+    by = c("date", "style")] %>%
+    tidyr::spread(style, `total users`, fill = 0) %>%
+    polloi::smoother(smooth_level = 
polloi::smooth_switch(input$smoothing_global, 
input$smoothing_tiles_users_series)) %>%
+    polloi::make_dygraph("Date", "Users", "Total users by style") %>%
+    dyAxis("y", logscale = input$tiles_users_logscale) %>%
+    dyLegend(labelsDiv = "tiles_users_series_legend", show = "always") %>%
+    dyRangeSelector %>%
+    dyEvent(as.Date("2015-09-17"), "A (announcement)", labelLoc = "bottom") %>%
+    dyEvent(as.Date("2016-01-08"), "B (enwiki launch)", labelLoc = "bottom") 
%>%
+    dyEvent(as.Date("2016-01-12"), "C (cache clear)", labelLoc = "bottom") %>%
+    dyEvent(as.Date("2016-11-08"), "D (pkget)", labelLoc = "top") %>%
+    dyEvent(as.Date("2017-01-01"), "R (reportupdater)", labelLoc = "bottom") 
%>%
+    dyEvent(as.Date("2017-08-14"), "E (pkget)", labelLoc = "bottom")
+})
+
+output$zoom_level_selector_container <- renderUI({
+  selectInput("zoom_level_selector", "Zoom level",
+              multiple = TRUE, selected = "0", selectize = FALSE, size = 19,
+              choices = as.character(sort(unique(new_tiles_no_automata$zoom))))
+})
+
+output$tiles_zoom_series <- renderDygraph({
+  req(input$zoom_level_selector)
+  polloi::data_select(
+    input$tile_zoom_automata_check,
+    new_tiles_automata,
+    new_tiles_no_automata
+  )[zoom %in% as.numeric(input$zoom_level_selector),
+    j = list(`total tiles` = sum(total)),
+    by = c("date", "zoom")] %>%
+    tidyr::spread(zoom, `total tiles`, fill = 0) %>%
+    polloi::smoother(smooth_level = 
polloi::smooth_switch(input$smoothing_global, 
input$smoothing_tiles_zoom_series)) %>%
+    polloi::make_dygraph("Date", "Tiles", "Total tiles by zoom level") %>%
+    dyAxis("y", logscale = input$tiles_zoom_logscale) %>%
+    dyLegend(labelsDiv = "tiles_zoom_series_legend", show = "always") %>%
+    dyEvent(as.Date("2017-01-01"), "R (reportupdater)", labelLoc = "bottom")
+})
diff --git a/server.R b/server.R
index eb642d5..0f8a627 100644
--- a/server.R
+++ b/server.R
@@ -12,8 +12,10 @@
     read_actions()
     progress$set(message = "Downloading EL user counts", value = 0.2)
     read_users()
+    progress$set(message = "Downloading prevalence data", value = 0.3)
+    read_prevalence()
     progress$set(message = "Downloading tile usage data", value = 0.4)
-    suppressWarnings(read_tiles())
+    # suppressWarnings(read_tiles())
     progress$set(message = "Downloading geography data", value = 0.8)
     read_countries()
     progress$set(message = "Finished downloading datasets", value = 1)
@@ -21,159 +23,14 @@
     progress$close()
   }
 
-  output$tiles_summary_series <- renderDygraph({
-    temp <- polloi::data_select(input$tile_summary_automata_check, 
new_tiles_automata, new_tiles_no_automata)[, list(
-      `total tiles` = sum(total),
-      `total users` = sum(users),
-      `average tiles per user` = sum(total)/sum(users)
-    ), by = "date"]
-    switch(input$tiles_summary_variable,
-           Users = { temp %<>% dplyr::select(-`total tiles`) },
-           Tiles = { temp %<>% dplyr::select(-`total users`) })
-    temp %<>% polloi::smoother(smooth_level = 
polloi::smooth_switch(input$smoothing_global, 
input$smoothing_tiles_summary_series))
-    polloi::make_dygraph(temp, "Date", input$tiles_summary_variable, "Tile 
usage") %>%
-      dySeries(name = grep('average tiles per user', names(temp), value = 
TRUE), axis = 'y2') %>%
-      dyAxis(name = 'y', drawGrid = FALSE, logscale = 
input$tiles_summary_logscale) %>%
-      dyAxis(name = 'y2', independentTicks = TRUE, drawGrid = FALSE) %>%
-      dyLegend(labelsDiv = "tiles_summary_series_legend", show = "always") %>%
-      dyRangeSelector(retainDateWindow = TRUE) %>%
-      dyEvent(as.Date("2015-09-17"), "A (announcement)", labelLoc = "bottom") 
%>%
-      dyEvent(as.Date("2016-01-08"), "B (enwiki launch)", labelLoc = "bottom") 
%>%
-      dyEvent(as.Date("2016-01-12"), "C (cache clear)", labelLoc = "bottom") 
%>%
-      dyEvent(as.Date("2016-11-09"), "D (pkget)", labelLoc = "bottom") %>%
-      dyEvent(as.Date("2017-01-01"), "R (reportupdater)", labelLoc = "bottom") 
%>%
-      dyEvent(as.Date("2017-08-14"), "E (pkget)", labelLoc = "bottom")
-  })
-
-  output$tiles_style_series <- renderDygraph({
-    polloi::data_select(
-      input$tile_style_automata_check,
-      new_tiles_automata,
-      new_tiles_no_automata
-    )[, j = list(`total tiles` = sum(total)),
-        by = c("date", "style")] %>%
-      tidyr::spread(style, `total tiles`, fill = 0) %>%
-      polloi::smoother(smooth_level = 
polloi::smooth_switch(input$smoothing_global, 
input$smoothing_tiles_style_series)) %>%
-      polloi::make_dygraph("Date", "Tiles", "Total tiles by style", 
legend_name = "Style") %>%
-      dyAxis("y", logscale = input$tiles_style_logscale) %>%
-      dyLegend(labelsDiv = "tiles_style_series_legend", show = "always") %>%
-      dyRangeSelector %>%
-      dyEvent(as.Date("2015-09-17"), "A (announcement)", labelLoc = "bottom") 
%>%
-      dyEvent(as.Date("2016-01-08"), "B (enwiki launch)", labelLoc = "bottom") 
%>%
-      dyEvent(as.Date("2016-01-12"), "C (cache clear)", labelLoc = "bottom") 
%>%
-      dyEvent(as.Date("2016-11-09"), "D (pkget)", labelLoc = "top") %>%
-      dyEvent(as.Date("2017-01-01"), "R (reportupdater)", labelLoc = "bottom") 
%>%
-      dyEvent(as.Date("2017-08-14"), "E (pkget)", labelLoc = "bottom")
-  })
-
-  output$tiles_users_series <- renderDygraph({
-    polloi::data_select(
-      input$tile_users_automata_check,
-      new_tiles_automata,
-      new_tiles_no_automata
-    )[, j = list(`total users` = sum(users)),
-        by = c("date", "style")] %>%
-      tidyr::spread(style, `total users`, fill = 0) %>%
-      polloi::smoother(smooth_level = 
polloi::smooth_switch(input$smoothing_global, 
input$smoothing_tiles_users_series)) %>%
-      polloi::make_dygraph("Date", "Users", "Total users by style") %>%
-      dyAxis("y", logscale = input$tiles_users_logscale) %>%
-      dyLegend(labelsDiv = "tiles_users_series_legend", show = "always") %>%
-      dyRangeSelector %>%
-      dyEvent(as.Date("2015-09-17"), "A (announcement)", labelLoc = "bottom") 
%>%
-      dyEvent(as.Date("2016-01-08"), "B (enwiki launch)", labelLoc = "bottom") 
%>%
-      dyEvent(as.Date("2016-01-12"), "C (cache clear)", labelLoc = "bottom") 
%>%
-      dyEvent(as.Date("2016-11-08"), "D (pkget)", labelLoc = "top") %>%
-      dyEvent(as.Date("2017-01-01"), "R (reportupdater)", labelLoc = "bottom") 
%>%
-      dyEvent(as.Date("2017-08-14"), "E (pkget)", labelLoc = "bottom")
-  })
-
-  output$zoom_level_selector_container <- renderUI({
-    selectInput("zoom_level_selector", "Zoom level",
-                multiple = TRUE, selected = "0", selectize = FALSE, size = 19,
-                choices = 
as.character(sort(unique(new_tiles_no_automata$zoom))))
-  })
-
-  output$tiles_zoom_series <- renderDygraph({
-    req(input$zoom_level_selector)
-    polloi::data_select(
-      input$tile_zoom_automata_check,
-      new_tiles_automata,
-      new_tiles_no_automata
-    )[zoom %in% as.numeric(input$zoom_level_selector),
-      j = list(`total tiles` = sum(total)),
-      by = c("date", "zoom")] %>%
-      tidyr::spread(zoom, `total tiles`, fill = 0) %>%
-      polloi::smoother(smooth_level = 
polloi::smooth_switch(input$smoothing_global, 
input$smoothing_tiles_zoom_series)) %>%
-      polloi::make_dygraph("Date", "Tiles", "Total tiles by zoom level") %>%
-      dyAxis("y", logscale = input$tiles_zoom_logscale) %>%
-      dyLegend(labelsDiv = "tiles_zoom_series_legend", show = "always") %>%
-      dyEvent(as.Date("2017-01-01"), "R (reportupdater)", labelLoc = "bottom")
-  })
-
-  output$users_per_platform <- renderDygraph({
-    user_data %>%
-      polloi::smoother(smooth_level = 
polloi::smooth_switch(input$smoothing_global, 
input$smoothing_users_per_platform)) %>%
-      polloi::make_dygraph("Date", "Events", "Unique users by platform, by 
day") %>%
-      dyAxis("y", logscale = input$users_per_platform_logscale) %>%
-      dyLegend(labelsDiv = "users_per_platform_legend", show = "always") %>%
-      dyRangeSelector %>%
-      dyEvent(as.Date("2016-04-15"), "A (Maps EL bug)", labelLoc = "bottom") 
%>%
-      dyEvent(as.Date("2016-06-17"), "A (Maps EL patch)", labelLoc = "bottom") 
%>%
-      dyEvent(as.Date("2017-01-01"), "R (reportupdater)", labelLoc = "bottom")
-  })
-
-  output$geohack_feature_usage <- renderDygraph({
-    usage_data$GeoHack %>%
-      polloi::smoother(smooth_level = 
polloi::smooth_switch(input$smoothing_global, 
input$smoothing_geohack_feature_usage)) %>%
-      polloi::make_dygraph("Date", "Events", "Feature usage for GeoHack") %>%
-      dyRangeSelector %>%
-      dyAxis("y", logscale = input$geohack_feature_usage_logscale) %>%
-      dyEvent(as.Date("2016-04-15"), "A (Maps EL bug)", labelLoc = "bottom") 
%>%
-      dyEvent(as.Date("2016-06-17"), "A (Maps EL patch)", labelLoc = "bottom") 
%>%
-      dyEvent(as.Date("2017-01-01"), "R (reportupdater)", labelLoc = "bottom")
-  })
-
-  output$wikiminiatlas_feature_usage <- renderDygraph({
-    usage_data$WikiMiniAtlas %>%
-      polloi::smoother(smooth_level = 
polloi::smooth_switch(input$smoothing_global, 
input$smoothing_wikiminiatlas_feature_usage)) %>%
-      polloi::make_dygraph("Date", "Events", "Feature usage for 
WikiMiniAtlas") %>%
-      dyRangeSelector %>%
-      dyAxis("y", logscale = input$wikiminiatlas_feature_usage_logscale) %>%
-      dyEvent(as.Date("2016-04-15"), "A (Maps EL bug)", labelLoc = "bottom") 
%>%
-      dyEvent(as.Date("2016-06-17"), "A (Maps EL patch)", labelLoc = "bottom") 
%>%
-      dyEvent(as.Date("2017-01-01"), "R (reportupdater)", labelLoc = "bottom")
-  })
-
-  output$wikivoyage_feature_usage <- renderDygraph({
-    usage_data$Wikivoyage %>%
-      polloi::smoother(smooth_level = 
polloi::smooth_switch(input$smoothing_global, 
input$smoothing_wikivoyage_feature_usage)) %>%
-      polloi::make_dygraph("Date", "Events", "Feature usage for Wikivoyage") 
%>%
-      dyRangeSelector %>%
-      dyAxis("y", logscale = input$wikivoyage_feature_usage_logscale) %>%
-      dyEvent(as.Date("2016-04-15"), "A (Maps EL bug)", labelLoc = "bottom") 
%>%
-      dyEvent(as.Date("2016-06-17"), "A (Maps EL patch)", labelLoc = "bottom") 
%>%
-      dyEvent(as.Date("2017-01-01"), "R (reportupdater)", labelLoc = "bottom")
-  })
-
-  output$wiwosm_feature_usage <- renderDygraph({
-    usage_data$WIWOSM %>%
-      polloi::smoother(smooth_level = 
polloi::smooth_switch(input$smoothing_global, 
input$smoothing_wiwosm_feature_usage)) %>%
-      polloi::make_dygraph("Date", "Events", "Feature usage for WIWOSM") %>%
-      dyRangeSelector %>%
-      dyAxis("y", logscale = input$wiwosm_feature_usage_logscale) %>%
-      dyEvent(as.Date("2016-04-15"), "A (Maps EL bug)", labelLoc = "bottom") 
%>%
-      dyEvent(as.Date("2016-06-17"), "A (Maps EL patch)", labelLoc = "bottom") 
%>%
-      dyEvent(as.Date("2017-01-01"), "R (reportupdater)", labelLoc = "bottom")
-  })
-
-
-  output$users_by_country <- renderDygraph({
-    country_data %>%
-      polloi::smoother(smooth_level = 
polloi::smooth_switch(input$smoothing_global, 
input$smoothing_users_by_country)) %>%
-      polloi::make_dygraph("Date", "Users (%)", "Geographic breakdown of maps 
users") %>%
-      dyRangeSelector(fillColor = "", strokeColor = "") %>%
-      dyEvent(as.Date("2017-01-01"), "R (reportupdater)", labelLoc = "bottom")
-  })
+  # Kartotherian usage (tile requests):
+  # source("modules/kartotherian.R", local = TRUE)
+  # Kartographer usage (maplink & mapframe):
+  source("modules/kartographer/overall_prevalence.R", local = TRUE)
+  source("modules/kartographer/language-project_breakdown.R", local = TRUE)
+  # Feature usage and geo-breakdown:
+  source("modules/feature_usage.R", local = TRUE)
+  source("modules/geographic_breakdown.R", local = TRUE)
 
   # Check datasets for missing data and notify user which datasets are missing 
data (if any)
   output$message_menu <- renderMenu({
@@ -183,7 +40,11 @@
       polloi::check_yesterday(user_data, "user counts"),
       polloi::check_past_week(user_data, "user counts"),
       polloi::check_yesterday(new_tiles_automata, "tile usage data"),
-      polloi::check_past_week(new_tiles_automata, "tile usage data"))
+      polloi::check_past_week(new_tiles_automata, "tile usage data"),
+      polloi::check_yesterday(maplink_prevalence, "maplink prevalence data"),
+      polloi::check_past_week(maplink_prevalence, "maplink prevalence data"),
+      polloi::check_yesterday(mapframe_prevalence, "mapframe prevalence data"),
+      polloi::check_past_week(mapframe_prevalence, "mapframe prevalence data"))
     notifications <- notifications[!sapply(notifications, is.null)]
     return(dropdownMenu(type = "notifications", .list = notifications, 
badgeStatus = "warning"))
   })
diff --git a/tab_documentation/overall_prevalence.md 
b/tab_documentation/overall_prevalence.md
new file mode 100644
index 0000000..29b00a0
--- /dev/null
+++ b/tab_documentation/overall_prevalence.md
@@ -0,0 +1,37 @@
+Overall maplink & mapframe usage
+=======
+
+[Kartographer](https://www.mediawiki.org/wiki/Extension:Kartographer) is a 
MediaWiki extension that allows editors to easily add [Wikimedia 
Maps](https://www.mediawiki.org/wiki/Maps) to articles. Editors (and bots) can 
add 
[*maplinks*](https://www.mediawiki.org/wiki/Help:Extension:Kartographer#.3Cmaplink.3E)
 and 
[*mapframes*](https://www.mediawiki.org/wiki/Help:Extension:Kartographer#.3Cmapframe.3E_usage)
 (where possible; refer to the list below) to pages such as places on 
Wikivoyage, landmarks on Wikipedia, and files on Wikimedia Commons.
+
+A **_maplink_** is a textual link (e.g. often coordinates) that a user can 
click on to view an interactive, potentially annotated map and is enabled on 
all Wikivoyage and Wikipedia languages. On Commons, camera coordinates -- which 
are automatically extracted from EXIF data for photo uploads -- show up as 
maplinks.
+
+A **_mapframe_** is a static thumbnail of a map that a user can click on to 
view an interactive, possibly annotated map and is enabled on all Wikivoyage 
languages but only some Wikipedias. As of September 18th, 2017, the mapframe 
feature is enabled on the following wikis:
+
+- [Metawiki](https://meta.wikimedia.org/)
+- [MediaWiki](https://www.mediawiki.org/)
+- [Wikimedia Ukraine](https://ua.wikimedia.org/)
+- [Wikivoyage](https://www.wikivoyage.org/) (all languages)
+- Wikipedia:
+    - [Catalan](https://ca.wikipedia.org/)
+    - [Hebrew](https://he.wikipedia.org/)
+    - [Russian](https://ru.wikipedia.org/)
+    - [Macedonian](https://mk.wikipedia.org/)
+    - [French](https://fr.wikipedia.org/)
+    - [Finnish](https://fi.wikipedia.org)
+    - [Norwegian](https://no.wikipedia.org/)
+    - [Swedish](https://sv.wikipedia.org/)
+    - [Portuguese](https://pt.wikipedia.org/)
+    - [Czech](https://cs.wikipedia.org/)
+    - [Basque](https://eu.wikipedia.org/)
+
+Questions, bug reports, and feature suggestions
+------
+For technical, non-bug questions, [email 
Mikhail](mailto:mpo...@wikimedia.org?subject=Dashboard%20Question) or 
[Chelsy](mailto:c...@wikimedia.org?subject=Dashboard%20Question). If you 
experience a bug or notice something wrong or have a suggestion, [open a ticket 
in 
Phabricator](https://phabricator.wikimedia.org/maniphest/task/create/?projects=Discovery)
 in the Discovery board or [email 
Deb](mailto:d...@wikimedia.org?subject=Dashboard%20Question).
+
+<hr style="border-color: gray;">
+<p style="font-size: small;">
+  <strong>Link to this dashboard:</strong> <a 
href="https://discovery.wmflabs.org/maps/#kartographer_prevalence";>https://discovery.wmflabs.org/maps/#kartographer_prevalence</a>
+  | Page is available under <a 
href="https://creativecommons.org/licenses/by-sa/3.0/"; title="Creative Commons 
Attribution-ShareAlike License">CC-BY-SA 3.0</a>
+  | <a href="https://phabricator.wikimedia.org/diffusion/WDWZ/"; 
title="Wikimedia Maps Dashboard source code repository">Code</a> is licensed 
under <a 
href="https://phabricator.wikimedia.org/diffusion/WDWZ/browse/master/LICENSE.md";
 title="MIT License">MIT</a>
+  | Part of <a href="https://discovery.wmflabs.org/";>Discovery Dashboards</a>
+</p>
diff --git a/tab_documentation/prevalence_langproj.md 
b/tab_documentation/prevalence_langproj.md
new file mode 100644
index 0000000..9dc3e0c
--- /dev/null
+++ b/tab_documentation/prevalence_langproj.md
@@ -0,0 +1,44 @@
+Maplink & mapframe prevalence by language and project
+=======
+
+[Kartographer](https://www.mediawiki.org/wiki/Extension:Kartographer) is a 
MediaWiki extension that allows editors to easily add [Wikimedia 
Maps](https://www.mediawiki.org/wiki/Maps) to articles. Editors (and bots) can 
add 
[*maplinks*](https://www.mediawiki.org/wiki/Help:Extension:Kartographer#.3Cmaplink.3E)
 and 
[*mapframes*](https://www.mediawiki.org/wiki/Help:Extension:Kartographer#.3Cmapframe.3E_usage)
 (where possible; refer to the list below) to pages such as places on 
Wikivoyage, landmarks on Wikipedia, and files on Wikimedia Commons.
+
+A **_maplink_** is a textual link (e.g. often coordinates) that a user can 
click on to view an interactive, potentially annotated map and is enabled on 
all Wikivoyage and Wikipedia languages. On Commons, camera coordinates -- which 
are automatically extracted from EXIF data for photo uploads -- show up as 
maplinks.
+
+A **_mapframe_** is a static thumbnail of a map that a user can click on to 
view an interactive, possibly annotated map and is enabled on all Wikivoyage 
languages but only some Wikipedias. As of September 18th, 2017, the mapframe 
feature is enabled on the following wikis:
+
+- [Metawiki](https://meta.wikimedia.org/)
+- [MediaWiki](https://www.mediawiki.org/)
+- [Wikimedia Ukraine](https://ua.wikimedia.org/)
+- [Wikivoyage](https://www.wikivoyage.org/) (all languages)
+- Wikipedia:
+    - [Catalan](https://ca.wikipedia.org/)
+    - [Hebrew](https://he.wikipedia.org/)
+    - [Russian](https://ru.wikipedia.org/)
+    - [Macedonian](https://mk.wikipedia.org/)
+    - [French](https://fr.wikipedia.org/)
+    - [Finnish](https://fi.wikipedia.org)
+    - [Norwegian](https://no.wikipedia.org/)
+    - [Swedish](https://sv.wikipedia.org/)
+    - [Portuguese](https://pt.wikipedia.org/)
+    - [Czech](https://cs.wikipedia.org/)
+    - [Basque](https://eu.wikipedia.org/)
+
+Notes
+-----
+
+* You can select multiple projects and multiple languages to compare 
simultaneously. (Hold down Ctrl on Windows or Command on Mac.)
+* __TODO__: The language picker will automatically choose "(None)" if you 
select a non-multilingual project such as Wikimedia Commons.
+* If you're interested in the overall metric for a multilingual project such 
as Wikipedia, make sure only "(None)" is selected in the languages picker.
+
+Questions, bug reports, and feature suggestions
+------
+For technical, non-bug questions, [email 
Mikhail](mailto:mpo...@wikimedia.org?subject=Dashboard%20Question) or 
[Chelsy](mailto:c...@wikimedia.org?subject=Dashboard%20Question). If you 
experience a bug or notice something wrong or have a suggestion, [open a ticket 
in 
Phabricator](https://phabricator.wikimedia.org/maniphest/task/create/?projects=Discovery)
 in the Discovery board or [email 
Deb](mailto:d...@wikimedia.org?subject=Dashboard%20Question).
+
+<hr style="border-color: gray;">
+<p style="font-size: small;">
+  <strong>Link to this dashboard:</strong> <a 
href="https://discovery.wmflabs.org/maps/#kartographer_langproj";>https://discovery.wmflabs.org/maps/#kartographer_langproj</a>
+  | Page is available under <a 
href="https://creativecommons.org/licenses/by-sa/3.0/"; title="Creative Commons 
Attribution-ShareAlike License">CC-BY-SA 3.0</a>
+  | <a href="https://phabricator.wikimedia.org/diffusion/WDWZ/"; 
title="Wikimedia Maps Dashboard source code repository">Code</a> is licensed 
under <a 
href="https://phabricator.wikimedia.org/diffusion/WDWZ/browse/master/LICENSE.md";
 title="MIT License">MIT</a>
+  | Part of <a href="https://discovery.wmflabs.org/";>Discovery Dashboards</a>
+</p>
diff --git a/tab_documentation/tiles_summary.md 
b/tab_documentation/tiles_summary.md
index 831ac2f..ddd7ba0 100644
--- a/tab_documentation/tiles_summary.md
+++ b/tab_documentation/tiles_summary.md
@@ -1,7 +1,7 @@
-Tiles (Summary)
+Kartotherian tile requests
 =======
 
-The initial usage spike was due to the announcement of the mapping service to 
the development community, and not the regular usage by Wikipedia users. Once 
the initial interest subsided, the usage fell back to the expected 
pre-announcement levels.
+The initial usage spike was due to the announcement of the mapping service to 
the development community, and not the regular usage by Wikipedia users. Once 
the initial interest subsided, the usage fell back to the expected 
pre-announcement levels until a Pokemon Go fan site "Pkget" switched to using 
Wikimedia Maps tiles after being blocked by OpenStreetMap.
 
 Notes
 -----
diff --git a/ui.R b/ui.R
index 5d1c207..c46eda7 100644
--- a/ui.R
+++ b/ui.R
@@ -13,11 +13,14 @@
         tags$script(src = "custom.js")
       ),
       sidebarMenu(id = "tabs",
-                  menuItem(text = "Tiles",
+                  menuItem(text = "Kartotherian usage",
                            menuSubItem(text = "Summary", tabName = 
"tiles_summary"),
                            menuSubItem(text = "Tiles by style", tabName = 
"tiles_total_by_style"),
                            menuSubItem(text = "Users by style", tabName = 
"tiles_users_by_style"),
                            menuSubItem(text = "Tiles by zoom level", tabName = 
"tiles_total_by_zoom")),
+                  menuItem(text = "Kartographer usage",
+                           menuSubItem(text = "Overall prevalence", tabName = 
"kartographer_prevalence"),
+                           menuSubItem(text = "Language/project breakdown", 
tabName = "kartographer_langproj")),
                   menuItem(text = "Platform usage", tabName = 
"platform_usage"),
                   menuItem(text = "Feature usage",
                            menuSubItem(text = "GeoHack", tabName = 
"geohack_usage"),
@@ -85,11 +88,53 @@
                     width = 4
                   )
                 ),
-                fluidRow(column(uiOutput("zoom_level_selector_container"), 
width = 3),
-                         column(dygraphOutput("tiles_zoom_series"), width = 
8)),
+                fluidRow(
+                  column(uiOutput("zoom_level_selector_container"), width = 3),
+                  column(dygraphOutput("tiles_zoom_series"), width = 8)
+                ),
                 polloi::automata_select("tile_zoom_automata_check"),
                 div(id = "tiles_zoom_series_legend", style = "text-align: 
right;"),
                 includeMarkdown("./tab_documentation/tiles_total_by_zoom.md")),
+        tabItem(tabName = "kartographer_prevalence",
+                dygraphOutput("overall_prevalence_series"),
+                div(id = "overall_prevalence_series_legend", style = 
"text-align: right;"),
+                includeMarkdown("./tab_documentation/overall_prevalence.md")),
+        tabItem(tabName = "kartographer_langproj",
+                fluidRow(
+                  
column(polloi::smooth_select("smoothing_prevalence_langproj"), width = 4),
+                  column(checkboxGroupInput(
+                    "prevalence_langproj_feature", "Feature",
+                    c("Mapframe", "Maplink"), inline = TRUE,
+                    selected = c("Mapframe", "Maplink")
+                  ), width = 4),
+                  column(
+                    HTML("<label class = \"control-label\" style = 
\"margin-bottom:-30px;\">Filtering</label>"),
+                    checkboxInput("prevalence_langproj_filter", "Exclude wikis 
with 0% prevalence from calculations", FALSE),
+                    width = 4
+                  )
+                ),
+                fluidRow(
+                  column(
+                    selectInput("language_order", "Sort languages by",
+                                list("Alphabetical order" = "alphabet", 
"Volume of articles" = "volume"),
+                                selected = "volume"),
+                    uiOutput("language_selector_container"),
+                    width = 2
+                  ),
+                  column(
+                    selectInput("project_order", "Sort projects by",
+                                list("Alphabetical order" = "alphabet", 
"Volume of articles" = "volume"),
+                                selected = "volume"),
+                    uiOutput("project_selector_container"),
+                    width = 2
+                  ),
+                  column(
+                    dygraphOutput("prevalence_langproj_plot"),
+                    div(id = "prevalence_langproj_legend", style = 
"text-align: right;"),
+                    width = 8
+                  )
+                ),
+                includeMarkdown("./tab_documentation/prevalence_langproj.md")),
         tabItem(tabName = "platform_usage",
                 fluidRow(
                   
column(polloi::smooth_select("smoothing_users_per_platform"), width = 3),
diff --git a/utils.R b/utils.R
index e060be7..cb50b6f 100644
--- a/utils.R
+++ b/utils.R
@@ -30,10 +30,91 @@
   return(invisible())
 }
 
-read_countries <- function(){
+read_countries <- function() {
   country_data <<- 
polloi::read_dataset("discovery/metrics/maps/users_by_country.tsv", col_types = 
"Dcd") %>%
     dplyr::filter(!is.na(country), !is.na(users)) %>%
     dplyr::mutate(users = users * 100) %>%
     tidyr::spread(country, users, fill = 0)
   return(invisible())
 }
+
+read_prevalence <- function() {
+  lang_proj <- polloi::get_langproj()
+  lang_proj$project <- ifelse(lang_proj$project == "Wikimedia Commons", 
"Commons", lang_proj$project)
+  maplinks <- 
polloi::read_dataset("discovery/metrics/maps/maplink_prevalence.tsv", col_types 
= "Dcii-")
+  mapframes <- 
polloi::read_dataset("discovery/metrics/maps/mapframe_prevalence.tsv", 
col_types = "Dcii-")
+  maplink_prevalence <<- maplinks %>%
+    dplyr::left_join(lang_proj, by = c("wiki" = "wikiid")) %>%
+    dplyr::filter(!is.na(project))
+  mapframe_prevalence <<- mapframes %>%
+    dplyr::left_join(lang_proj, by = c("wiki" = "wikiid")) %>%
+    dplyr::filter(!is.na(project))
+  available_languages_maplink <- maplink_prevalence %>%
+    dplyr::mutate(language = dplyr::if_else(is.na(language), "(None)", 
language)) %>%
+    dplyr::group_by(language) %>%
+    dplyr::top_n(1, date) %>%
+    dplyr::summarize(articles = sum(total_articles), maplink = TRUE) %>%
+    dplyr::ungroup() %>%
+    dplyr::select(c(language, articles, maplink))
+  available_languages_mapframe <- mapframe_prevalence %>%
+    dplyr::mutate(language = dplyr::if_else(is.na(language), "(None)", 
language)) %>%
+    dplyr::group_by(language) %>%
+    dplyr::top_n(1, date) %>%
+    dplyr::summarize(articles = sum(total_articles), mapframe = TRUE) %>%
+    dplyr::ungroup() %>%
+    dplyr::select(c(language, articles, mapframe))
+  available_languages <<- dplyr::full_join(
+    available_languages_maplink,
+    available_languages_mapframe,
+    by = "language"
+  ) %>%
+    dplyr::mutate(
+      articles = pmax(articles.x, articles.y, na.rm = TRUE),
+      maplink = dplyr::if_else(is.na(maplink), FALSE, maplink),
+      mapframe = dplyr::if_else(is.na(mapframe), FALSE, mapframe)
+    ) %>%
+    dplyr::select(-c(articles.x, articles.y))
+  available_projects_maplink <- maplink_prevalence %>%
+    dplyr::group_by(project) %>%
+    dplyr::top_n(1, date) %>%
+    dplyr::summarize(articles = sum(total_articles), maplink = TRUE) %>%
+    dplyr::ungroup() %>%
+    dplyr::select(c(project, articles, maplink))
+  available_projects_mapframe <- mapframe_prevalence %>%
+    dplyr::group_by(project) %>%
+    dplyr::top_n(1, date) %>%
+    dplyr::summarize(articles = sum(total_articles), mapframe = TRUE) %>%
+    dplyr::ungroup() %>%
+    dplyr::select(c(project, articles, mapframe))
+  available_projects <<- dplyr::full_join(
+    available_projects_maplink,
+    available_projects_mapframe,
+    by = "project"
+  ) %>%
+    dplyr::mutate(
+      articles = pmax(articles.x, articles.y, na.rm = TRUE),
+      maplink = dplyr::if_else(is.na(maplink), FALSE, maplink),
+      mapframe = dplyr::if_else(is.na(mapframe), FALSE, mapframe)
+    ) %>%
+    dplyr::select(-c(articles.x, articles.y))
+  prevalence <<- dplyr::inner_join(
+    maplinks, mapframes,
+    by = c("date", "wiki")
+  ) %>%
+    dplyr::left_join(lang_proj, by = c("wiki" = "wikiid")) %>%
+    dplyr::filter(!is.na(project)) %>%
+    dplyr::select(-wiki) %>%
+    dplyr::group_by(date, project) %>%
+    dplyr::summarize(
+      Maplink = round(100 * sum(maplink_articles) / sum(total_articles.x), 2),
+      Mapframe = round(100 * sum(mapframe_articles) / sum(total_articles.y), 2)
+    ) %>%
+    dplyr::ungroup() %>%
+    tidyr::gather(feature, prevalence, -c(date, project)) %>%
+    dplyr::transmute(
+      date = date, prevalence = prevalence,
+      group = paste0(feature, " (", project, ")")
+    ) %>%
+    tidyr::spread(group, prevalence)
+  return(invisible())
+}

-- 
To view, visit https://gerrit.wikimedia.org/r/379150
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: If1f1efa619037ce8adea873c148f9a1f78376506
Gerrit-PatchSet: 1
Gerrit-Project: wikimedia/discovery/wetzel
Gerrit-Branch: develop
Gerrit-Owner: Bearloga <mpo...@wikimedia.org>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to