Code
library('ggplot2')
library('dplyr')
# r_functions <- list.files(file.path(here::here(), "src", "R"), "\\.R$", full.names = TRUE)
#
# purrr::map(r_functions, source) |>
# purrr::quietly()
Final project proposal assigned. | Exercise 04 assigned.
February 20, 2025
February 19, 2025
This page extracts information about illustrations of Gestalt principles that students found as part of their work on 2025-02-13. Data are pulled from the shared Google Sheet.
Direct link: https://docs.google.com/spreadsheets/d/1G8U_IPMP0x17Sfl-FQfF37DN19bDQFm0GO_UmQQzv7Q/edit?usp=sharing
First, we load the external packages (groups of R commands) that we will be using.
The code uses the quietly()
function from the purrr
package to suppress most of the feedback.
Next, we download the data from the Google Sheet where it is collected. Dr. Gilmore has stored his Google account credentials in a special environment file that can be accessed by the R command Sys.getenv("GMAIL_SURVEY")
.
It’s vital to be very careful when creating and sharing code like this that involves sensitive information like login credentials.
Gilmore likes to put credentials in an .Renviron
file that lives in his home directory. This is a recommended practice. On Mac OS and Linux, that’s ~/.Renviron
. You can use the usethis::edit_r_profile()
command at the R console (not the Terminal) to open your own .Renviron
file. In Gilmore’s case, he has added the following line to that file:
GMAIL_SURVEY="<my-google-account>"
Here, he has substituted his Google account with credentials/access to the required files for <my-google-account>
. Then, when the R code below calls Sys.getenv("GMAIL_SURVEY")
, the value of those credentials is returned as a text string.
Make sure to close and save the .Renviron
file and restart your R session before testing this yourself.
if (!dir.exists('csv')) {
message("Creating missing `csv/`.")
dir.create("csv")
}
if (params$update_data) {
options(gargle_oauth_email = Sys.getenv("GMAIL_SURVEY"))
googledrive::drive_auth()
googledrive::drive_download(
params$google_sheet_name,
path = file.path("csv", params$fn),
type = "csv",
overwrite = TRUE
)
message("Data updated.")
} else {
message("Using stored data.")
}
The data file has been saved as a comma-separated value (CSV) format data file in a special directory called csv/
.
Next we load the saved data file, and then proceed to clean it.
There are 22 responses.
These are the column/variable names.
[1] "identifier" "gestalt_principle" "url_src"
[4] "url_to_img"
For simplicity, we visualize below only those with non-empty URLs to the specific figure.
There were n=14 unique respondents.
Of the 22 responses from these individuals or teams, n=13 had URLs we could link to directly with non-data-visualization figures.
make_img_markdown_from_url <- function(img_url = "https://www.psychologicalscience.org/redesign/wp-content/uploads/2015/12/TCD_fig_1.jpg",
lightbox = "{.lightbox}") {
assertthat::is.string(img_url)
component_1 <- paste0("
component_2 <- paste0(img_url, ")", lightbox)
paste0(component_1, component_2)
}
return_img_chunk <- function(i, df) {
assertthat::is.number(i)
assertthat::assert_that(i > 0)
assertthat::assert_that(is.data.frame(df))
df_i <- df[i,]
chunk_hdr_txt <- paste0("### Figure ", i, "\n\n")
chunk_hdr <- knitr::knit_expand(text = chunk_hdr_txt)
if (!is.na(df_i$url_to_img)) {
img_markdown <- make_img_markdown_from_url(df_i$url_to_img)
} else {
img_markdown = "**No direct link to figure**"
}
body_txt <- paste0("\n\n| Analyst | Principle | \n|---|---|\n",
"| ", df_i$identifier, " | ", df_i$gestalt_principle, "|")
knitr::knit_child(
text = c(chunk_hdr, img_markdown, body_txt),
envir = environment(),
quiet = TRUE
)
}
Analyst | Principle |
---|---|
HRQ | Closure |
Analyst | Principle |
---|---|
HRQ | Closure |
Analyst | Principle |
---|---|
TJD | Continuity |
Analyst | Principle |
---|---|
TJD | Continuity |
Analyst | Principle |
---|---|
SS | Closure |
Analyst | Principle |
---|---|
JVM | Proximity |
Analyst | Principle |
---|---|
ABC | Continuity |
Analyst | Principle |
---|---|
ABC | Continuity |
Analyst | Principle |
---|---|
KVV | Closure |
Analyst | Principle |
---|---|
KVV | Closure |
Analyst | Principle |
---|---|
ac | Continuity |
Analyst | Principle |
---|---|
NA | NA |
Analyst | Principle |
---|---|
pp | Reification |
url_src |
---|
https://www.wikiart.org/en/salvador-dali/face-of-mae-west-which-may-be-used-as-an-apartment |
https://www.olympics.com/ioc/olympic-rings |
https://www.census.gov/library/visualizations/interactive/state-private-nonres-construction-spending.html |
https://www.behance.net/gallery/18122387/Gestalt-Principles |
https://nastengraph.medium.com/gestalt-principles-in-data-visualization-a4e56e6074b5 |
https://www.uxdesigninstitute.com/blog/gestalt-principles-ux-ui-design/ |
https://towardsdatascience.com/the-psychology-behind-data-visualization-techniques-68ef12865720/ |
https://pmc.ncbi.nlm.nih.gov/articles/PMC3728284/ |
https://wbispace.usc.edu/gestalt.html |
https://www.pinterest.com/pin/355854808061515950/sent/?invite_code=838115ec6814476584ca76ff24e9d590&sfo=1 |
---
title: "Gestalt in the wild"
format: html
params:
update_data: true
google_sheet_name: 'PSYCH 490.003-Gestalt-Examples'
fn: gestalt_examples.csv
---
## About
This page extracts information about illustrations of Gestalt principles that students found as part of their work on [2025-02-13](../slides/wk05-2025-02-13-sensation-to-perception.qmd). Data are pulled from the shared Google Sheet.
## Data
Direct link: <https://docs.google.com/spreadsheets/d/1G8U_IPMP0x17Sfl-FQfF37DN19bDQFm0GO_UmQQzv7Q/edit?usp=sharing>
<iframe src="https://docs.google.com/spreadsheets/d/1G8U_IPMP0x17Sfl-FQfF37DN19bDQFm0GO_UmQQzv7Q/edit?usp=sharing" width="640" height="800" frameborder="0" marginheight="0" marginwidth="0">Loading…</iframe>
## Preparation
First, we load the external packages (groups of R commands) that we will be using.
::: {.callout-important}
The code uses the `quietly()` function from the `purrr` package to suppress most of the feedback.
:::
```{r}
#| warning: false
library('ggplot2')
library('dplyr')
# r_functions <- list.files(file.path(here::here(), "src", "R"), "\\.R$", full.names = TRUE)
#
# purrr::map(r_functions, source) |>
# purrr::quietly()
```
## Gathering
Next, we download the data from the Google Sheet where it is collected.
Dr. Gilmore has stored his Google account credentials in a special environment file that can be accessed by the R command `Sys.getenv("GMAIL_SURVEY")`.
::: {.callout-tip}
It's vital to be *very* careful when creating and sharing code like this that involves sensitive information like login credentials.
Gilmore likes to put credentials in an `.Renviron` file that lives in his home directory.
This is a [recommended practice](https://support.posit.co/hc/en-us/articles/360047157094-Managing-R-with-Rprofile-Renviron-Rprofile-site-Renviron-site-rsession-conf-and-repos-conf).
On Mac OS and Linux, that's `~/.Renviron`.
You can use the `usethis::edit_r_profile()` command *at the R console* (not the Terminal) to open your own `.Renviron` file.
In Gilmore's case, he has added the following line to that file:
```
GMAIL_SURVEY="<my-google-account>"
```
Here, he has substituted his Google account with credentials/access to the required files for `<my-google-account>`.
Then, when the R code below calls `Sys.getenv("GMAIL_SURVEY")`, the value of those credentials is returned as a text string.
Make sure to close and save the `.Renviron` file and restart your R session before testing this yourself.
:::
```{r, eval=params$update_data}
#| label: gather-data-from-google
#| message: false
#| echo: true
if (!dir.exists('csv')) {
message("Creating missing `csv/`.")
dir.create("csv")
}
if (params$update_data) {
options(gargle_oauth_email = Sys.getenv("GMAIL_SURVEY"))
googledrive::drive_auth()
googledrive::drive_download(
params$google_sheet_name,
path = file.path("csv", params$fn),
type = "csv",
overwrite = TRUE
)
message("Data updated.")
} else {
message("Using stored data.")
}
```
The data file has been saved as a comma-separated value (CSV) format data file in a special directory called `csv/`.
## Cleaning
Next we load the saved data file, and then proceed to clean it.
```{r, eval=params$update_data}
#| label: load-saved-data
#| message: false
#| echo: true
gestalt <-
readr::read_csv(file.path("csv", params$fn), show_col_types = FALSE)
```
There are `{r} dim(gestalt)[1]` responses.
These are the column/variable names.
```{r}
# Google Forms puts the full question in the top row of the data file.
# We use the names() function to extract and print the original questions.
gestalt_qs <- names(gestalt)
gestalt_qs
```
For simplicity, we visualize below only those with non-empty URLs to the specific figure.
## Summary data
```{r}
figs_w_urls <- gestalt |>
filter(!is.na(url_to_img)) |>
filter(stringr::str_detect(url_to_img, "[png|jpg|webp]$"))
```
There were *n*=`{r} length(unique(gestalt$identifier))` unique respondents.
Of the `{r} dim(gestalt)[1]` responses from these individuals or teams, *n*=`{r} dim(figs_w_urls)[1]` had URLs we could link to directly with non-data-visualization figures.
## Make helper functions
```{r}
make_img_markdown_from_url <- function(img_url = "https://www.psychologicalscience.org/redesign/wp-content/uploads/2015/12/TCD_fig_1.jpg",
lightbox = "{.lightbox}") {
assertthat::is.string(img_url)
component_1 <- paste0("
component_2 <- paste0(img_url, ")", lightbox)
paste0(component_1, component_2)
}
return_img_chunk <- function(i, df) {
assertthat::is.number(i)
assertthat::assert_that(i > 0)
assertthat::assert_that(is.data.frame(df))
df_i <- df[i,]
chunk_hdr_txt <- paste0("### Figure ", i, "\n\n")
chunk_hdr <- knitr::knit_expand(text = chunk_hdr_txt)
if (!is.na(df_i$url_to_img)) {
img_markdown <- make_img_markdown_from_url(df_i$url_to_img)
} else {
img_markdown = "**No direct link to figure**"
}
body_txt <- paste0("\n\n| Analyst | Principle | \n|---|---|\n",
"| ", df_i$identifier, " | ", df_i$gestalt_principle, "|")
knitr::knit_child(
text = c(chunk_hdr, img_markdown, body_txt),
envir = environment(),
quiet = TRUE
)
}
```
## Figures found
```{r many-tables-lapply, results = "asis", warning=FALSE}
res <- invisible(lapply(1:dim(figs_w_urls)[1], return_img_chunk, df = figs_w_urls))
cat(unlist(res), sep = "\n")
```
## Sites found
```{r}
gestalt |>
filter(!is.na(url_src)) |>
filter(stringr::str_detect(url_src, "^https://")) |>
dplyr::select(url_src) |>
# dplyr::mutate(url_src = paste0("<", url_src, ">")) |>
knitr::kable(format = 'html')
```