From 1f8c28bbc880ca6ad58b98ac373d33a3d99e2a20 Mon Sep 17 00:00:00 2001 From: Ja Young Lee Date: Tue, 1 Sep 2020 13:18:07 -0700 Subject: [PATCH 1/3] Update plot_functions.R Exclude options correctly from matrix questions. --- survey-analysis/plot_functions.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/survey-analysis/plot_functions.R b/survey-analysis/plot_functions.R index 4ba466c..c22021f 100644 --- a/survey-analysis/plot_functions.R +++ b/survey-analysis/plot_functions.R @@ -335,7 +335,7 @@ f.matrix <- function(qNum, set <- set.wide %>% gather("category") %>% group_by(category, value) %>% - filter(value != "", !value %in% exclude) %>% + filter(value != "", !value %in% exclude, !category %in% exclude) %>% tally() %>% mutate(p = n/sum(n)) %>% mutate(me = 1.96 * sqrt(p * (1-p) / n)) From 92ca6eeaace3154acac42f19b1b1f24380c9662e Mon Sep 17 00:00:00 2001 From: Ja Young Lee Date: Tue, 15 Sep 2020 11:00:22 -0700 Subject: [PATCH 2/3] Update plot_functions Update regex to correctly extract strings from multi-select questions --- survey-analysis/plot_functions.R | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/survey-analysis/plot_functions.R b/survey-analysis/plot_functions.R index c22021f..01e32c0 100644 --- a/survey-analysis/plot_functions.R +++ b/survey-analysis/plot_functions.R @@ -201,7 +201,7 @@ f.singlechoice_breakout <- function(qNum, p <- ggplot(set, aes(x = category.n, y = p, fill = rating)) + geom_bar(position = "fill", stat = "identity", width = 0.8) + - ggtitle(plot_title)+ + ggtitle(plot_title) + scale_fill_manual(values = palette, labels = labels) + guides(fill = guide_legend(reverse = T)) + add_text_stacked + add_percent_scale + @@ -241,10 +241,12 @@ f.multiplechoice <- function(qNum, if(is.null(data)) data <- all - choices <- sub('.+-(.+)', - '\\1', - questions %>% - select(starts_with(qNum), -ends_with("TEXT"), -ends_with("RANK"))) + choices <- str_remove( + str_extract( + questions %>% + select(starts_with(qNum), -ends_with("TEXT"), -ends_with("RANK")), + "[.]-[:alpha:].+"), + ".-") set.wide <- data %>% select(starts_with(qNum)) %>% @@ -319,10 +321,13 @@ f.matrix <- function(qNum, height = 4) { if(is.null(data)) data <- all - - choices <- sub('.+-(.+)', - '\\1', - questions %>% dplyr::select(starts_with(qNum)) %>% dplyr::select(-ends_with("TEXT"))) + + choices <- str_remove( + str_extract( + questions %>% + select(starts_with(qNum), -ends_with("TEXT"), -ends_with("RANK")), + "-[:Upper:].+"), + "-") set.wide <- data %>% select(starts_with(qNum)) %>% From c60354645012dde6fd0fa259baee0970ff4a4268 Mon Sep 17 00:00:00 2001 From: Ja Young Lee Date: Thu, 7 Dec 2023 15:16:22 -0800 Subject: [PATCH 3/3] Add more ordering options and minor fixes --- survey-analysis/plot_constants.R | 8 ++- survey-analysis/plot_functions.R | 105 +++++++++++++++++++++---------- 2 files changed, 77 insertions(+), 36 deletions(-) diff --git a/survey-analysis/plot_constants.R b/survey-analysis/plot_constants.R index 60896fc..976f851 100644 --- a/survey-analysis/plot_constants.R +++ b/survey-analysis/plot_constants.R @@ -7,7 +7,7 @@ primary = "#1075C2" gray100 = "#D5D7DA" gray600 = "#60646B" color_palette_flutter_5 = c(flutter_blue, primary_dark, primary, gray100, gray600) -color_palette_monochrome = rep(primary, 20) +color_palette_monochrome = rep(primary, 50) color_palette_5 = c("#003f5c", "#58508d", "#bc5090", "#ff6361", "#ffa600") color_palette_8 = c("#003f5c", "#2f4b7c", "#665191", "#a05195", "#d45087", "#f95d6a", "#ff7c43", "#ffa600") color_palette_19 = c("#512DA8", "#009688", "#FFC107", "#607D8B", "#FF5252", "#303F9F", "#388E3C", "#F57C00", @@ -26,6 +26,8 @@ satisfaction_plus1 = c("Very satisfied", "Somewhat satisfied", "Neither satisfi "I don’t have enough experience with it to answer this question") satisfaction_wrap = c("Very \nsatisfied", "Somewhat \nsatisfied", "Neither satisfied \nnor dissatisfied", "Somewhat \ndissatisfied", "Very \ndissatisfied") +agree = c("Strongly agree", "Somewhat agree", "Neither agree nor disagree", "Somewhat disagree", "Strongly disagree") +agree_wrap = c("Strongly\nagree", "Somewhat\nagree", "Neither agree\nnor disagree", "Somewhat\ndisagree", "Strongly\ndisagree") usefulness = c("Extremely useful", "Very useful", "Somewhat useful", "Slightly useful", "Not at all useful") difficulty = c("Very easy", "Somewhat easy", "Neither easy nor difficult", "Somewhat difficult", "Very difficult") frequency = c("Almost always", "Often", "Sometimes", "Rarely", "Nearly never") @@ -37,7 +39,7 @@ dev_stage = c("Published a complete production app", "Published a demo "I am not developing an app for this platform in Flutter") experience_level = c("No experience", "Awareness", "Novice", "Intermediate", "Advanced", "Expert") tenure = c("Less than 3 months", "3 to 6 months", "6 to 12 months", "Over a year") -company_size = c("1 person", "2-9 employees", "10-99 employees", "100-999 employees", +company_size = c("1 employee", "2-9 employees", "10-99 employees", "100-999 employees", "1,000-9,999 employees", "Over 10,000 employees") team_size = c("Just me", "2-4", "5-9", "10-19", "20-49", "More than 50") -mau = c("1-999", "1,000 - 9,999", "10,000 - 99,999", "100,000 - 999,999", "1million+") \ No newline at end of file +mau = c("1-999", "1,000-9,999", "10,000-99,999", "100,000-999,999", "1 million+") diff --git a/survey-analysis/plot_functions.R b/survey-analysis/plot_functions.R index 01e32c0..7d8222f 100644 --- a/survey-analysis/plot_functions.R +++ b/survey-analysis/plot_functions.R @@ -23,33 +23,38 @@ f.setcolors <- function(colors, length) { } # ------------------------------ Presets ------------------------------ + add_conf_intv <- geom_errorbar(aes(ymin = p - me, ymax = p + me), position = position_dodge(width = 0.9), width = 0.1, colour = "grey40") -add_text <- geom_text_repel(aes(label = paste0(round(100 * p), "% ")), +add_text <- geom_text_repel(aes(label = paste0(round(100 * p, digits = 1), "% ")), position = position_dodge(width = 0.9), direction = "x", + bg.color = "grey30", + bg.r = 0.01, size = 3, hjust = 0, colour = "white") -add_text_stacked <- geom_text_repel(aes(label = paste0(round(100*p), "% ")), - hjust = 1, - vjust = 1, +add_text_stacked <- geom_text_repel(aes(label = paste0(round(100*p, digits = 1), "% ")), + vjust = 0, + hjust = 0.5, size = 3, colour = "white", + bg.color = "grey30", + bg.r = 0.01, position = "stack", point.padding = NA, ylim = c(0, 1)) theme_custom <- theme_minimal() + - theme(text = element_text(family = "Roboto", size = 10), - plot.title = element_text(family = "Roboto", size = 10), - axis.title = element_blank()) + theme(text = element_text(family = "Roboto", size = 12), + plot.title = element_text(family = "Roboto", size = 12), + axis.title = element_blank()) theme_custom_top <- theme_custom + theme(legend.position="top") add_percent_scale <- scale_y_continuous(labels = scales::percent, name = "") - +wrap_text <- scale_x_discrete(labels = function(x) str_wrap(x, width = 40)) # ------------------------------ Plotting functions ------------------------------ @@ -107,11 +112,11 @@ f.singlechoice <- function(qNum, geom_bar(aes(fill = rating), stat = "identity", width = 0.8) + add_conf_intv + add_text + ggtitle(plot_title)+ - scale_x_discrete(limits = rev(levels(set$rating))) + + scale_x_discrete(limits = rev(levels(set$rating))) + # , labels = function(x) str_wrap(x, width = 40) scale_y_continuous(labels = scales::percent) + - scale_fill_manual(values = palette, guide = F) + # c(primary, gray600) + scale_fill_manual(values = palette, guide = "none") + # c(primary, gray600) coord_flip() + - theme_custom + theme_custom if(!is.null(filename)) { ggsave(paste0("figures/", filename, ".png"), @@ -144,7 +149,7 @@ f.singlechoice_breakout <- function(qNum, data = NULL, title = NULL, orders = NULL, - by = NULL, + orders_bo = NULL, colors = NULL, labels = NULL, q_exclude = c(), @@ -174,25 +179,37 @@ f.singlechoice_breakout <- function(qNum, group_by(category) %>% mutate(category.n = paste0(category, "\n(N = ", sum(n), ")")) - # TODO: Make it possible to order the categories too (add another parameter) if(is.null(orders)) { rating_order_by_n <- set %>% group_by(rating) %>% summarise(sump = sum(p)) %>% arrange(desc(sump)) %>% - select(rating) %>% + dplyr::select(rating) %>% sapply(factor) set$rating <- factor(set$rating, levels = rating_order_by_n) category_order_by_n <- set %>% ungroup() %>% filter(rating == rating_order_by_n[1]) %>% arrange(desc(p)) %>% - select(category.n) %>% + dplyr::select(category.n) %>% sapply(factor) set$category.n <- factor(set$category.n, levels = category_order_by_n) } else { set$rating <- factor(set$rating, levels = orders) + category_order_by_factor <- set %>% ungroup() %>% + filter(rating == levels(set$rating)[1]) %>% + arrange(desc(p)) %>% + dplyr::select(category.n) %>% + sapply(factor) + set$category.n <- factor(set$category.n, levels = category_order_by_factor) + } + + if(!is.null(orders_bo)) { + set$category <- factor(set$category, levels = orders_bo) + x = set[order(set$category), "category.n"] + set$category.n <- factor(set$category.n, levels = unique(x)$category.n) } + palette <- f.setcolors(colors, length(unique(set$rating))) if(is.null(labels)) { @@ -205,7 +222,8 @@ f.singlechoice_breakout <- function(qNum, scale_fill_manual(values = palette, labels = labels) + guides(fill = guide_legend(reverse = T)) + add_text_stacked + add_percent_scale + - coord_flip() + theme_custom_top + coord_flip() + + theme_custom_top if(!is.null(filename)) { ggsave(paste0("figures/", filename, ".png"), @@ -240,16 +258,18 @@ f.multiplechoice <- function(qNum, height = 4) { if(is.null(data)) data <- all + + select <- dplyr::select choices <- str_remove( str_extract( questions %>% - select(starts_with(qNum), -ends_with("TEXT"), -ends_with("RANK")), - "[.]-[:alpha:].+"), - ".-") + select(starts_with(paste0(qNum,"_")), -ends_with("TEXT"), -ends_with("RANK")), + "-[1-9a-zA-Z].+"), + "-") set.wide <- data %>% - select(starts_with(qNum)) %>% + select(starts_with(paste0(qNum,"_"))) %>% select(-ends_with("TEXT"), -ends_with("RANK")) %>% filter_all(any_vars(.!="")) %>% rename_at(vars(starts_with(qNum)), ~choices) @@ -285,14 +305,14 @@ f.multiplechoice <- function(qNum, p <- ggplot(set , aes(x = category, y = p)) + geom_bar(stat = "identity", aes(fill = category), width = 0.8) + ggtitle(plot_title) + - scale_fill_manual(values = palette, guide = F) + + scale_fill_manual(values = palette, guide = "none") + add_conf_intv + add_text + add_percent_scale + xlab("") + coord_flip() + - theme_custom + theme_custom + wrap_text if(!is.null(filename)) ggsave(paste0("figures/", filename, ".png"), p, width = width, height = height) - + print(set) return(p) } @@ -309,28 +329,34 @@ f.multiplechoice <- function(qNum, # labels* (Add a vector of labels, if you want to include custom labels for a smaller legend.) # width, height (Set the size of output plot) +# filename = NULL; data = NULL; exclude = c(); title = NULL; orders = NULL; colors = NULL; labels = NULL; width = 8; height = 4 + f.matrix <- function(qNum, filename = NULL, data = NULL, exclude = c(), title = NULL, orders = NULL, + orders2 = NULL, colors = NULL, labels = NULL, width = 8, - height = 4) { + height = 4, + table = FALSE) { if(is.null(data)) data <- all + select <- dplyr::select + choices <- str_remove( str_extract( questions %>% - select(starts_with(qNum), -ends_with("TEXT"), -ends_with("RANK")), - "-[:Upper:].+"), + select(starts_with(paste0(qNum,"_")), -ends_with("TEXT"), -ends_with("RANK")), + "-[a-zA-Z].+"), "-") set.wide <- data %>% - select(starts_with(qNum)) %>% + select(starts_with(paste0(qNum,"_"))) %>% select(-ends_with("TEXT")) %>% rename_at(vars(starts_with(qNum)), ~choices) %>% filter_all(any_vars(.!="")) @@ -346,7 +372,7 @@ f.matrix <- function(qNum, mutate(me = 1.96 * sqrt(p * (1-p) / n)) # TODO: Make it possible to order the categories too (add another parameter) - if(is.null(orders)) { + if(is.null(orders) & is.null(orders2)) { value_order_by_n <- set %>% group_by(value) %>% summarise(sump = sum(p)) %>% @@ -360,14 +386,26 @@ f.matrix <- function(qNum, select(category) %>% sapply(factor) set$category <- factor(set$category, levels = category_order_by_n) - } else { + } else if (!is.null(orders) & is.null(orders)) { set$value <- factor(set$value, levels = orders) category_order <- set %>% filter(value == orders[1]) %>% arrange(desc(p)) %>% select(category) %>% sapply(factor) - set$category <- factor(set$category, levels = category_order) + set$category <- factor(set$category, levels = category_order) + } else if(is.null(orders) & !is.null(orders2)) { + value_order_by_n <- set %>% + group_by(value) %>% + summarise(sump = sum(p)) %>% + arrange(desc(sump)) %>% + select(value) %>% + sapply(factor) + set$value <- factor(set$value, levels = value_order_by_n) + set$category <- factor(set$category, levels = orders2) + } else if(!is.null(orders) & !is.null(orders2)) { + set$value <- factor(set$value, levels = orders) + set$category <- factor(set$category, levels = orders2) } palette = f.setcolors(colors, length(unique(set$value))) @@ -389,12 +427,13 @@ f.matrix <- function(qNum, add_text_stacked + add_percent_scale + coord_flip() + - theme_custom_top + guides(fill = guide_legend(reverse = T)) + theme_custom_top + guides(fill = guide_legend(reverse = T)) + + wrap_text if(!is.null(filename)) ggsave(paste0("figures/", filename, ".png"), p, width = width, height = height) - - return(p) + if(table == TRUE) {return(list(set, p))} else {return (p)} + # return(p) }