Data Preperation - Teacher Study

Author

Julius Fenn

Published

December 9, 2025

Background Information

This is an R Markdown document. Instructions for writing these documents and background information can be found in the book written by Xie, Allaire, and Grolemund (2018) When you execute code within the document, the results appear beneath the code. This is an R Markdown document. Instructions for writing these documents and background information can be found in the book written by Xie, Allaire, and Grolemund (2018) When you execute code within the document, the results appear beneath the code. This file contains summary statistics, respectively the analysis step (confirmatory and exploratory analyses). Files are split into multiple subfiles like data processing and data analyses steps, which follows the classical data-analysis pipeline (see Peng and Matsui 2016; Wickham and Grolemund 2017).

Setup

Global variables

save_CAMs_as_pictures = TRUE
# consider_Protocol = FALSE # not needed at current stage

Load packages

require(pacman)
Lade nötiges Paket: pacman
p_load('tidyverse', 'jsonlite', 'magrittr',
       'stargazer', 'psych', 'jtools', 'DT', 'igraph',
       'writexl', 'Cairo')

Check your raw data:

### list data files
setwd("data")
folders <- list.files(pattern = "^study_result.*")



for(i in 1:length(folders)){
  setwd(folders[i])
  if(length(dir()) == 3){
    cat("\n ################## \n")
    print(i)
    
    # pre CAM data
    setwd(dir()[1])
    tmp <- jsonlite::fromJSON(txt = "data.txt")
    tmp_id <- tmp$ID[!is.na(tmp$ID)]
    cat("01:\n")
    cat("tmp_id:", tmp_id, "\n")
    cat("sender:", tmp$sender[!is.na(tmp$sender)], "\n")
    setwd("..")
    
    # tmp_backup <- tmp
    
    # CAM data t1
    setwd(dir()[2])
    tmp2 <- jsonlite::fromJSON(txt = "data.txt")
    
    # tmp_backup2 <- tmp2
    
    cat("02:\n")
    cat("tmp2$creator:", tmp2$creator, "\n")
    # print(tmp2$projectCAM)
    # print(tmp2$creator)
    # print(length(tmp2$nodes))
    setwd("..")
    
    # post CAM data
    setwd(dir()[3])
    tmp <- jsonlite::fromJSON(txt = "data.txt")
    tmp_id <- tmp$ID[!is.na(tmp$ID)]
    cat("03:\n")
    cat("tmp_id:", tmp_id, "\n")
    cat("sender:", tmp$sender[!is.na(tmp$sender)], "\n")
    setwd("..")
    
    
    cat("\n")
  }
  setwd("..")
}

 ################## 
[1] 6
01:
tmp_id: 578843 
sender: Greetings InformedConsent InformedConsentNO socioDemographic Videopage CAMsDetailedInst 
02:
tmp2$creator: 578843 
03:
tmp_id: 
sender: CAMfeedbackGeneral additional scale SCALES Sequence DonationScreen FeedbackScreen EndingScreen 


 ################## 
[1] 11
01:
tmp_id: 238101 
sender: Greetings InformedConsent InformedConsentNO socioDemographic Videopage CAMsDetailedInst 
02:
tmp2$creator: 238101 
03:
tmp_id: 
sender: CAMfeedbackGeneral additional scale SCALES Sequence DonationScreen FeedbackScreen EndingScreen 


 ################## 
[1] 12
01:
tmp_id: 858644 
sender: Greetings InformedConsent InformedConsentNO socioDemographic Videopage CAMsDetailedInst 
02:
tmp2$creator: 858644 
03:
tmp_id: 
sender: CAMfeedbackGeneral additional scale SCALES Sequence DonationScreen FeedbackScreen EndingScreen 


 ################## 
[1] 19
01:
tmp_id: 376106 
sender: Greetings InformedConsent InformedConsentNO socioDemographic Videopage CAMsDetailedInst 
02:
tmp2$creator: 376106 
03:
tmp_id: 
sender: CAMfeedbackGeneral additional scale SCALES Sequence DonationScreen FeedbackScreen EndingScreen 


 ################## 
[1] 22
01:
tmp_id: 35549 
sender: Greetings InformedConsent InformedConsentNO socioDemographic Videopage CAMsDetailedInst 
02:
tmp2$creator: 35549 
03:
tmp_id: 
sender: CAMfeedbackGeneral additional scale SCALES Sequence DonationScreen FeedbackScreen EndingScreen 


 ################## 
[1] 27
01:
tmp_id: 128115 
sender: Greetings InformedConsent InformedConsentNO socioDemographic Videopage CAMsDetailedInst 
02:
tmp2$creator: 128115 
03:
tmp_id: 
sender: CAMfeedbackGeneral additional scale SCALES Sequence DonationScreen FeedbackScreen EndingScreen 


 ################## 
[1] 28
01:
tmp_id: 702927 
sender: Greetings InformedConsent InformedConsentNO socioDemographic Videopage CAMsDetailedInst 
02:
tmp2$creator: 702927 
03:
tmp_id: 
sender: CAMfeedbackGeneral additional scale SCALES Sequence DonationScreen FeedbackScreen EndingScreen 


 ################## 
[1] 33
01:
tmp_id: 432155 
sender: Greetings InformedConsent InformedConsentNO socioDemographic Videopage CAMsDetailedInst 
02:
tmp2$creator: 432155 
03:
tmp_id: 
sender: CAMfeedbackGeneral additional scale SCALES Sequence DonationScreen FeedbackScreen EndingScreen 


 ################## 
[1] 35
01:
tmp_id: 29087 
sender: Greetings InformedConsent InformedConsentNO socioDemographic Videopage CAMsDetailedInst 
02:
tmp2$creator: 29087 
03:
tmp_id: 
sender: CAMfeedbackGeneral additional scale SCALES Sequence DonationScreen FeedbackScreen 


 ################## 
[1] 38
01:
tmp_id: 293295 
sender: Greetings InformedConsent InformedConsentNO socioDemographic Videopage CAMsDetailedInst 
02:
tmp2$creator: 293295 
03:
tmp_id: 
sender: CAMfeedbackGeneral additional scale SCALES Sequence DonationScreen FeedbackScreen EndingScreen 


 ################## 
[1] 39
01:
tmp_id: 330258 
sender: Greetings InformedConsent InformedConsentNO socioDemographic Videopage CAMsDetailedInst 
02:
tmp2$creator: 330258 
03:
tmp_id: 
sender: CAMfeedbackGeneral additional scale SCALES Sequence DonationScreen FeedbackScreen EndingScreen 


 ################## 
[1] 41
01:
tmp_id: 555046 
sender: Greetings InformedConsent InformedConsentNO socioDemographic Videopage CAMsDetailedInst 
02:
tmp2$creator: 555046 
03:
tmp_id: 
sender: CAMfeedbackGeneral additional scale SCALES Sequence DonationScreen FeedbackScreen EndingScreen 


 ################## 
[1] 52
01:
tmp_id: 976767 
sender: Greetings InformedConsent InformedConsentNO socioDemographic Videopage CAMsDetailedInst 
02:
tmp2$creator: 976767 
03:
tmp_id: 
sender: CAMfeedbackGeneral additional scale SCALES Sequence DonationScreen FeedbackScreen EndingScreen 


 ################## 
[1] 54
01:
tmp_id: 106962 
sender: Greetings InformedConsent InformedConsentNO socioDemographic Videopage CAMsDetailedInst 
02:
tmp2$creator: 106962 
03:
tmp_id: 
sender: CAMfeedbackGeneral additional scale SCALES Sequence DonationScreen FeedbackScreen EndingScreen 


 ################## 
[1] 55
01:
tmp_id: 621540 
sender: Greetings InformedConsent InformedConsentNO socioDemographic Videopage CAMsDetailedInst 
02:
tmp2$creator: 621540 
03:
tmp_id: 
sender: CAMfeedbackGeneral additional scale SCALES Sequence DonationScreen FeedbackScreen EndingScreen 


 ################## 
[1] 64
01:
tmp_id: 389317 
sender: Greetings InformedConsent InformedConsentNO socioDemographic Videopage CAMsDetailedInst 
02:
tmp2$creator: 389317 
03:
tmp_id: 
sender: CAMfeedbackGeneral additional scale SCALES Sequence DonationScreen FeedbackScreen EndingScreen 


 ################## 
[1] 68
01:
tmp_id: 217750 
sender: Greetings InformedConsent InformedConsentNO socioDemographic Videopage CAMsDetailedInst 
02:
tmp2$creator: 217750 
03:
tmp_id: 
sender: CAMfeedbackGeneral additional scale SCALES Sequence DonationScreen FeedbackScreen EndingScreen 


 ################## 
[1] 70
01:
tmp_id: 70044 
sender: Greetings InformedConsent InformedConsentNO socioDemographic Videopage CAMsDetailedInst 
02:
tmp2$creator: 70044 
03:
tmp_id: 
sender: CAMfeedbackGeneral additional scale SCALES Sequence DonationScreen FeedbackScreen EndingScreen 


 ################## 
[1] 72
01:
tmp_id: 245939 
sender: Greetings InformedConsent InformedConsentNO socioDemographic Videopage CAMsDetailedInst 
02:
tmp2$creator: 245939 
03:
tmp_id: 
sender: CAMfeedbackGeneral additional scale SCALES Sequence DonationScreen FeedbackScreen EndingScreen 


 ################## 
[1] 74
01:
tmp_id: 557688 
sender: Greetings InformedConsent InformedConsentNO socioDemographic Videopage CAMsDetailedInst 
02:
tmp2$creator: 557688 
03:
tmp_id: 
sender: CAMfeedbackGeneral additional scale SCALES Sequence DonationScreen FeedbackScreen EndingScreen 


 ################## 
[1] 75
01:
tmp_id: 361656 
sender: Greetings InformedConsent InformedConsentNO socioDemographic Videopage CAMsDetailedInst 
02:
tmp2$creator: 361656 
03:
tmp_id: 
sender: CAMfeedbackGeneral additional scale SCALES Sequence DonationScreen FeedbackScreen EndingScreen 


 ################## 
[1] 76
01:
tmp_id: 404139 
sender: Greetings InformedConsent InformedConsentNO socioDemographic Videopage CAMsDetailedInst 
02:
tmp2$creator: 404139 
03:
tmp_id: 
sender: CAMfeedbackGeneral additional scale SCALES Sequence DonationScreen FeedbackScreen EndingScreen 


 ################## 
[1] 81
01:
tmp_id: 876120 
sender: Greetings InformedConsent InformedConsentNO socioDemographic Videopage CAMsDetailedInst 
02:
tmp2$creator: 876120 
03:
tmp_id: 
sender: CAMfeedbackGeneral additional scale SCALES Sequence DonationScreen FeedbackScreen EndingScreen 


 ################## 
[1] 82
01:
tmp_id: 493193 
sender: Greetings InformedConsent InformedConsentNO socioDemographic Videopage CAMsDetailedInst 
02:
tmp2$creator: 493193 
03:
tmp_id: 
sender: CAMfeedbackGeneral additional scale SCALES Sequence DonationScreen FeedbackScreen EndingScreen 


 ################## 
[1] 85
01:
tmp_id: 378506 
sender: Greetings InformedConsent InformedConsentNO socioDemographic Videopage CAMsDetailedInst 
02:
tmp2$creator: 378506 
03:
tmp_id: 
sender: CAMfeedbackGeneral additional scale SCALES Sequence DonationScreen FeedbackScreen EndingScreen 


 ################## 
[1] 86
01:
tmp_id: 382902 
sender: Greetings InformedConsent InformedConsentNO socioDemographic Videopage CAMsDetailedInst 
02:
tmp2$creator: 382902 
03:
tmp_id: 
sender: CAMfeedbackGeneral additional scale SCALES Sequence DonationScreen FeedbackScreen EndingScreen 


 ################## 
[1] 91
01:
tmp_id: 978703 
sender: Greetings InformedConsent InformedConsentNO socioDemographic Videopage CAMsDetailedInst 
02:
tmp2$creator: 978703 
03:
tmp_id: 
sender: CAMfeedbackGeneral additional scale SCALES Sequence DonationScreen FeedbackScreen EndingScreen 


 ################## 
[1] 92
01:
tmp_id: 174178 
sender: Greetings InformedConsent InformedConsentNO socioDemographic Videopage CAMsDetailedInst 
02:
tmp2$creator: 174178 
03:
tmp_id: 
sender: CAMfeedbackGeneral additional scale SCALES Sequence DonationScreen FeedbackScreen EndingScreen 


 ################## 
[1] 93
01:
tmp_id: 403724 
sender: Greetings InformedConsent InformedConsentNO socioDemographic Videopage CAMsDetailedInst 
02:
tmp2$creator: 403724 
03:
tmp_id: 
sender: CAMfeedbackGeneral additional scale SCALES Sequence DonationScreen FeedbackScreen EndingScreen 


 ################## 
[1] 94
01:
tmp_id: 789471 
sender: Greetings InformedConsent InformedConsentNO socioDemographic Videopage CAMsDetailedInst 
02:
tmp2$creator: 789471 
03:
tmp_id: 
sender: CAMfeedbackGeneral additional scale SCALES Sequence DonationScreen FeedbackScreen EndingScreen 


 ################## 
[1] 95
01:
tmp_id: 746986 
sender: Greetings InformedConsent InformedConsentNO socioDemographic Videopage CAMsDetailedInst 
02:
tmp2$creator: 746986 
03:
tmp_id: 
sender: CAMfeedbackGeneral additional scale SCALES Sequence DonationScreen FeedbackScreen EndingScreen 


 ################## 
[1] 97
01:
tmp_id: 729193 
sender: Greetings InformedConsent InformedConsentNO socioDemographic Videopage CAMsDetailedInst 
02:
tmp2$creator: 729193 
03:
tmp_id: 
sender: CAMfeedbackGeneral additional scale SCALES Sequence DonationScreen FeedbackScreen EndingScreen 


 ################## 
[1] 106
01:
tmp_id: 396705 
sender: Greetings InformedConsent InformedConsentNO socioDemographic Videopage CAMsDetailedInst 
02:
tmp2$creator: 396705 
03:
tmp_id: 
sender: CAMfeedbackGeneral additional scale SCALES Sequence DonationScreen FeedbackScreen EndingScreen 


 ################## 
[1] 119
01:
tmp_id: 170802 
sender: Greetings InformedConsent InformedConsentNO socioDemographic Videopage CAMsDetailedInst 
02:
tmp2$creator: 170802 
03:
tmp_id: 
sender: CAMfeedbackGeneral additional scale SCALES Sequence DonationScreen FeedbackScreen EndingScreen 


 ################## 
[1] 131
01:
tmp_id: 524362 
sender: Greetings InformedConsent InformedConsentNO socioDemographic Videopage CAMsDetailedInst 
02:
tmp2$creator: 524362 
03:
tmp_id: 
sender: CAMfeedbackGeneral additional scale SCALES Sequence DonationScreen FeedbackScreen EndingScreen 


 ################## 
[1] 136
01:
tmp_id: 272874 
sender: Greetings InformedConsent InformedConsentNO socioDemographic Videopage CAMsDetailedInst 
02:
tmp2$creator: 272874 
03:
tmp_id: 
sender: CAMfeedbackGeneral additional scale SCALES Sequence DonationScreen FeedbackScreen EndingScreen 
rm(tmp); rm(tmp2)

create raw data files

### list data files
setwd("data")
folders <- list.files(pattern = "^study_result.*")

### create data files - GERMANY
# get CAM data
writeLines("", "CAM_t1.txt") # create file
text_connection <-
  file("CAM_t1.txt", "a") # open connection to append


# get pre CAM data
writeLines("", "preCAM.txt") # create file
text_connection_pre <-
  file("preCAM.txt", "a") # open connection to append

# get post CAM data
writeLines("", "postCAM.txt") # create file
text_connection_post <-
  file("postCAM.txt", "a") # open connection to append



for (i in 1:length(folders)) {
  setwd(folders[i])
  if (length(dir()) == 3) {
    # print(i)
    
    # pre CAM data
    setwd(dir()[1])
    tmp1 <- jsonlite::fromJSON(txt = "data.txt")
    tmp_id <- tmp1$ID[!is.na(tmp1$ID)]
    setwd("..")
    
    
    # CAM data
    setwd(dir()[2])
    tmp2 <- jsonlite::fromJSON(txt = "data.txt")
    if (!("creator" %in% names(tmp2)) || tmp2$creator != tmp_id) {
      warning("IDs (primary keys) not matching or order of datasets is distorted - 1")
      tmp2 <- NULL
    }
    setwd("..")
    
    
    
    # post CAM data
    setwd(dir()[3])
    tmp3 <- jsonlite::fromJSON(txt = "data.txt")
    tmp3$ID <- NA
    tmp3$ID[2] <- tmp_id
    
    setwd("..")
    
    cat("checks for i:", i, !is.null(tmp1) &&
        !is.null(tmp2) &&
        !is.null(tmp3), "\n")
    
    
    if (!is.null(tmp1) &&
        !is.null(tmp2) &&
        !is.null(tmp3)) {
      writeLines(jsonlite::toJSON(x = tmp1), text_connection_pre)
      writeLines(jsonlite::toJSON(x = tmp2), text_connection)
      writeLines(jsonlite::toJSON(x = tmp3), text_connection_post)
    }
  }
  setwd("..")
}
checks for i: 6 TRUE 
checks for i: 11 TRUE 
checks for i: 12 TRUE 
checks for i: 19 TRUE 
checks for i: 22 TRUE 
checks for i: 27 TRUE 
checks for i: 28 TRUE 
checks for i: 33 TRUE 
checks for i: 35 TRUE 
checks for i: 38 TRUE 
checks for i: 39 TRUE 
checks for i: 41 TRUE 
checks for i: 52 TRUE 
checks for i: 54 TRUE 
checks for i: 55 TRUE 
checks for i: 64 TRUE 
checks for i: 68 TRUE 
checks for i: 70 TRUE 
checks for i: 72 TRUE 
checks for i: 74 TRUE 
checks for i: 75 TRUE 
checks for i: 76 TRUE 
checks for i: 81 TRUE 
checks for i: 82 TRUE 
checks for i: 85 TRUE 
checks for i: 86 TRUE 
checks for i: 91 TRUE 
checks for i: 92 TRUE 
checks for i: 93 TRUE 
checks for i: 94 TRUE 
checks for i: 95 TRUE 
checks for i: 97 TRUE 
checks for i: 106 TRUE 
checks for i: 119 TRUE 
checks for i: 131 TRUE 
checks for i: 136 TRUE 
close(text_connection) # close connection CAM
close(text_connection_pre) # close connection
close(text_connection_post) # close connection

### move files to output folder
# copy files (not overwritten)
tmp_file_from <-  getwd()
setwd("../outputs/data_raw")
file.copy(
  from =  paste0(tmp_file_from, "/CAM_t1.txt"),
  to = paste0(getwd(), "/CAM_t1.txt")
)
[1] TRUE
file.copy(
  from =  paste0(tmp_file_from, "/preCAM.txt"),
  to = paste0(getwd(), "/preCAM.txt")
)
[1] TRUE
file.copy(
  from =  paste0(tmp_file_from, "/postCAM.txt"),
  to = paste0(getwd(), "/postCAM.txt")
)
[1] TRUE
# remove files
file.remove(paste0(tmp_file_from, "/CAM_t1.txt"))
[1] TRUE
file.remove(paste0(tmp_file_from, "/preCAM.txt"))
[1] TRUE
file.remove(paste0(tmp_file_from, "/postCAM.txt"))
[1] TRUE
### load functions
# print(getwd())
setwd("../../../../functions")
for (i in 1:length(dir())) {
  # print(dir()[i])
  source(dir()[i], encoding = "utf-8")
}


setwd("../functions_CAMapp")
for (i in 1:length(dir())) {
  # print(dir()[i])
  source(dir()[i], encoding = "utf-8")
}
rm(i)


rm(tmp1)
rm(tmp2)
rm(tmp3)
rm(tmp_id)
rm(folders)
rm(tmp_file_from)
rm(text_connection)
rm(text_connection_pre)
rm(text_connection_post)

set up data.frame questionnaires

load data:

setwd("outputs/data_raw")
# > pre study
suppressMessages(read_file('preCAM.txt') %>%
                   # ... split it into lines ...
                   str_split('\n') %>% first() %>%
                   # ... filter empty rows ...
                   discard(function(x) x == '') %>%
                   discard(function(x) x == '\r') %>%
                   # ... parse JSON into a data.frame
                   map_dfr(fromJSON, flatten=TRUE)) -> dat_preCAM

# > post first CAM
suppressMessages(read_file('postCAM.txt') %>%
                   # ... split it into lines ...
                   str_split('\n') %>% first() %>%
                   # ... filter empty rows ...
                   discard(function(x) x == '') %>%
                   discard(function(x) x == '\r') %>%
                   # ... parse JSON into a data.frame
                   map_dfr(fromJSON, flatten=TRUE)) -> dat_postCAM
colnames(dat_preCAM)[colnames(dat_preCAM) == "ID"] <- "uniqueID"
colnames(dat_postCAM)[colnames(dat_postCAM) == "ID"] <- "uniqueID"

sum(!is.na(dat_preCAM$uniqueID))
[1] 36
sum(!is.na(dat_postCAM$uniqueID))
[1] 36

add unique ID variable to match rows to participants, only keep complete data sets:

### create counter variable for both data sets
# pre study
dat_preCAM$ID <- NA

tmp_IDcounter <- 0
for(i in 1:nrow(dat_preCAM)){
  if(!is.na(dat_preCAM$sender[i]) && dat_preCAM$sender[i] == "Greetings"){
    tmp_IDcounter = tmp_IDcounter + 1
  }
  dat_preCAM$ID[i] <- tmp_IDcounter
}



# post study
dat_postCAM$ID <- NA

tmp_IDcounter <- 0
for(i in 1:nrow(dat_postCAM)){
  if(!is.na(dat_postCAM$sender[i]) && dat_postCAM$sender[i] == "CAMfeedbackGeneral"){
    tmp_IDcounter = tmp_IDcounter + 1
  }
  dat_postCAM$ID[i] <- tmp_IDcounter
}





### keep only complete data sets
# pre-study
# sort(table(dat_preCAM$ID))
sum(table(dat_preCAM$ID) != max(table(dat_preCAM$ID)))
[1] 0
sum(table(dat_preCAM$ID) == max(table(dat_preCAM$ID)))
[1] 36
dat_preCAM <- dat_preCAM[dat_preCAM$ID %in% names(table(dat_preCAM$ID))[table(dat_preCAM$ID) == max(table(dat_preCAM$ID))],]

# post-study
# sort(table(dat_postCAM$ID))
sum(table(dat_postCAM$ID) != max(table(dat_postCAM$ID)))
[1] 1
sum(table(dat_postCAM$ID) == max(table(dat_postCAM$ID)))
[1] 35
dat_postCAM <- dat_postCAM[dat_postCAM$ID %in% names(table(dat_postCAM$ID))[table(dat_postCAM$ID) == max(table(dat_postCAM$ID))],]




all(unique(dat_preCAM$ID) %in% unique(dat_postCAM$ID))
[1] FALSE

rename ID variable for data sets:

questionnaire pre-study (component 1)

colnames(dat_preCAM)
 [1] "sender"                        "sender_type"                  
 [3] "sender_id"                     "6"                            
 [5] "ended_on"                      "duration"                     
 [7] "time_run"                      "time_render"                  
 [9] "time_show"                     "time_end"                     
[11] "time_commit"                   "timestamp"                    
[13] "time_switch"                   "para_defocuscount"            
[15] "currentLocation"               "IDtype"                       
[17] "uniqueID"                      "dummy_informedconsent"        
[19] "sociodemo_age"                 "sociodemo_gender"             
[21] "sociodemo_language"            "sociodemo_subjects_taught"    
[23] "sociodemo_school_types"        "sociodemo_teaching_experience"
[25] "meta.labjs_version"            "meta.location"                
[27] "meta.userAgent"                "meta.platform"                
[29] "meta.language"                 "meta.locale"                  
[31] "meta.timeZone"                 "meta.timezoneOffset"          
[33] "meta.screen_width"             "meta.screen_height"           
[35] "meta.scroll_width"             "meta.scroll_height"           
[37] "meta.window_innerWidth"        "meta.window_innerHeight"      
[39] "meta.devicePixelRatio"         "meta.labjs_build.flavor"      
[41] "meta.labjs_build.commit"       "7"                            
[43] "ID"                           
tmp_notNumeric <- str_subset(string = colnames(dat_preCAM), pattern = "^meta|^R")
tmp_notNumeric <- str_subset(string = tmp_notNumeric, pattern = "labjs|location", negate = TRUE)

tmp_notNumeric <- c(tmp_notNumeric, "sociodemo_gender", "sociodemo_language", "sociodemo_subjects_taught", "sociodemo_school_types")

vec_ques <- c("uniqueID",
              "currentLocation", "IDtype",
              "dummy_informedconsent", 
              "commCheck",
              "sociodemo_age", "sociodemo_gender", "sociodemo_language", "sociodemo_subjects_taught", "sociodemo_school_types", "sociodemo_teaching_experience",
              tmp_notNumeric)


vec_notNumeric = c("uniqueID", "currentLocation", "IDtype", tmp_notNumeric)

questionnaire_c1 <- questionnairetype(dataset = dat_preCAM, 
                                        listvars = vec_ques, 
                                        notNumeric = vec_notNumeric, verbose = FALSE)


dim(questionnaire_c1)
[1] 36 24
colnames(questionnaire_c1)
 [1] "ID"                            "uniqueID"                     
 [3] "currentLocation"               "IDtype"                       
 [5] "dummy_informedconsent"         "sociodemo_age"                
 [7] "sociodemo_gender"              "sociodemo_language"           
 [9] "sociodemo_subjects_taught"     "sociodemo_school_types"       
[11] "sociodemo_teaching_experience" "meta.userAgent"               
[13] "meta.platform"                 "meta.language"                
[15] "meta.locale"                   "meta.timeZone"                
[17] "meta.timezoneOffset"           "meta.screen_width"            
[19] "meta.screen_height"            "meta.scroll_width"            
[21] "meta.scroll_height"            "meta.window_innerWidth"       
[23] "meta.window_innerHeight"       "meta.devicePixelRatio"        

questionnaire post-CAM (component 3)

colnames(dat_postCAM)
 [1] "sender"                     "sender_type"               
 [3] "sender_id"                  "feedCAM_repres"            
 [5] "ease_mindmap"               "feedCAM_technicalprobs"    
 [7] "feedCAM_technicalprobsText" "feedCAM_already"           
 [9] "feedCAM_alreadyText"        "10"                        
[11] "ended_on"                   "duration"                  
[13] "time_run"                   "time_render"               
[15] "time_show"                  "time_end"                  
[17] "time_commit"                "timestamp"                 
[19] "time_switch"                "guttman-item"              
[21] "not_needed"                 "guttman-response"          
[23] "uniqueID"                   "para_countclicks"          
[25] "education-4"                "education-1"               
[27] "education-3"                "education-2"               
[29] "donation_choice"            "feedback_critic"           
[31] "para_defocuscount"          "11"                        
[33] "ID"                        
vec_ques <- c("uniqueID",
              "feedCAM_repres", 
              "ease_mindmap",
              "feedCAM_technicalprobs", "feedCAM_technicalprobsText",
              "feedCAM_already", "feedCAM_alreadyText",
              sort(str_subset(string = colnames(dat_postCAM), pattern = "^education")),
              "donation_choice",
              "feedback_critic")

vec_notNumeric = c("uniqueID", 
                   "feedCAM_technicalprobsText", "feedCAM_alreadyText", "donation_choice", "feedback_critic")

questionnaire_c3 <- questionnairetype(dataset = dat_postCAM, 
                                        listvars = vec_ques, 
                                        notNumeric = vec_notNumeric, verbose = TRUE)
[1] 1
[1] "uniqueID"
[1] 2
[1] "feedCAM_repres"
[1] 3
[1] "ease_mindmap"
[1] 4
[1] "feedCAM_technicalprobs"
[1] 5
[1] "feedCAM_technicalprobsText"
[1] 6
[1] "feedCAM_already"
[1] 7
[1] "feedCAM_alreadyText"
[1] 8
[1] "education-1"
[1] 9
[1] "education-2"
[1] 10
[1] "education-3"
[1] 11
[1] "education-4"
[1] 12
[1] "donation_choice"
[1] 13
[1] "feedback_critic"
dim(questionnaire_c3)
[1] 35 14
colnames(questionnaire_c3)
 [1] "ID"                         "uniqueID"                  
 [3] "feedCAM_repres"             "ease_mindmap"              
 [5] "feedCAM_technicalprobs"     "feedCAM_technicalprobsText"
 [7] "feedCAM_already"            "feedCAM_alreadyText"       
 [9] "education-1"                "education-2"               
[11] "education-3"                "education-4"               
[13] "donation_choice"            "feedback_critic"           

get ratings of law and guttman

# Pre-define the column names with rat_ pattern
guttman_cols <- sort(str_subset(string = colnames(dat_postCAM), pattern = "^guttman"))

# to merge data sets
# for(i in 1:length(guttman_cols)){
#   dat_postCAM[[guttman_cols[i]]] <- NA
# }

# Create an empty list to store processed data
result_list <- list()

dat_merged <- dat_postCAM[, c("ID", "uniqueID", "sender", guttman_cols)]
dat_merged$`guttman-response`[!is.na(dat_merged$`guttman-item`) & dat_merged$`guttman-response` == "NA"] <- "LNA"

# Loop over each unique ID
for (i in unique(dat_merged$ID)) {
  tmp <- dat_merged[dat_merged$ID == i, c("uniqueID", "sender", guttman_cols)]
  
  # Fill down uniqueID if missing
  tmp <- tmp %>%
    fill(uniqueID, .direction = "downup")
  
  # Filter rows where all rat_ columns are not NA
tmp <- tmp %>% 
  filter(
    if_any(all_of(guttman_cols), ~ !is.na(.))     # at least one guttman_* value present
  )
tmp$sender[is.na(tmp$sender)] <- paste0("GI_", tmp$`guttman-item`[!is.na(tmp$`guttman-item`)])
  
  # Append to result list
  result_list[[as.character(i)]] <- tmp
}

# Combine all into one dataframe
questionnaire_rating_long <- bind_rows(result_list)
questionnaire_rating_long$sender <- factor(questionnaire_rating_long$sender)


# wide data set for guttman ratings
colnames(questionnaire_rating_long)[colnames(questionnaire_rating_long) == "guttman-item"] <- "item"
colnames(questionnaire_rating_long)[colnames(questionnaire_rating_long) == "guttman-response"] <- "response"

questionnaire_rating_wide_guttman <- questionnaire_rating_long %>%
  pivot_wider(
    id_cols = uniqueID,
    names_from = item,
    values_from = response,
    names_glue = "response_{item}"
  )

merge all data sets

# Start with the first dataset
merged_data <- questionnaire_c1

# Left join the others one by one
merged_data <- merged_data %>%
  left_join(questionnaire_c3, by = "uniqueID") %>%
  left_join(questionnaire_rating_wide_guttman, by = "uniqueID")


merged_data$ID.x <- NULL
merged_data$ID.y <- NULL

dim(merged_data)
[1] 36 39
colnames(merged_data)
 [1] "uniqueID"                      "currentLocation"              
 [3] "IDtype"                        "dummy_informedconsent"        
 [5] "sociodemo_age"                 "sociodemo_gender"             
 [7] "sociodemo_language"            "sociodemo_subjects_taught"    
 [9] "sociodemo_school_types"        "sociodemo_teaching_experience"
[11] "meta.userAgent"                "meta.platform"                
[13] "meta.language"                 "meta.locale"                  
[15] "meta.timeZone"                 "meta.timezoneOffset"          
[17] "meta.screen_width"             "meta.screen_height"           
[19] "meta.scroll_width"             "meta.scroll_height"           
[21] "meta.window_innerWidth"        "meta.window_innerHeight"      
[23] "meta.devicePixelRatio"         "feedCAM_repres"               
[25] "ease_mindmap"                  "feedCAM_technicalprobs"       
[27] "feedCAM_technicalprobsText"    "feedCAM_already"              
[29] "feedCAM_alreadyText"           "education-1"                  
[31] "education-2"                   "education-3"                  
[33] "education-4"                   "donation_choice"              
[35] "feedback_critic"               "response_1"                   
[37] "response_4"                    "response_3"                   
[39] "response_2"                   

save all data sets

setwd("outputs/questionnaire")

# Save as .RData objects
save(questionnaire_c1, file = "questionnaire_c1.RData")
save(questionnaire_c3, file = "questionnaire_c3.RData")
save(merged_data, file = "merged_data.RData")
save(questionnaire_rating_long, file = "questionnaire_rating_long.RData")

# Save as Excel files
write_xlsx(questionnaire_c1, "questionnaire_c1.xlsx")
write_xlsx(questionnaire_c3, "questionnaire_c3.xlsx")
write_xlsx(merged_data, "merged_data.xlsx")
write_xlsx(questionnaire_rating_long, "questionnaire_rating_long.xlsx")

set up CAM data

pre CAM (component 2)

Load CAM data

setwd("outputs/data_raw")
suppressMessages(read_file("CAM_t1.txt") %>%
  # ... split it into lines ...
  str_split('\n') %>% first() %>%
    discard(function(x) x == '') %>%
    discard(function(x) x == '\r') %>%
  # ... filter empty rows ...
  discard(function(x) x == '')) -> dat_CAM_pre

raw_CAM_pre <- list()
for(i in 1:length(dat_CAM_pre)){
  raw_CAM_pre[[i]] <- jsonlite::fromJSON(txt = dat_CAM_pre[[i]])
}

Create CAM files, draw CAMs and compute network indicators

### create CAM single files (nodes, connectors, merged)
CAMfiles_pre <- create_CAMfiles(datCAM = raw_CAM_pre, reDeleted = TRUE)
Nodes and connectors, which were deleted by participants were removed. 
 # deleted nodes:  164 
 # deleted connectors:  57
# remove testing data sets
nrow(CAMfiles_pre[[1]])
[1] 719
# CAMfiles_pre[[1]] <- CAMfiles_pre[[1]][nchar(CAMfiles_pre[[1]]$participantCAM) == 24,]
# CAMfiles_pre[[2]] <- CAMfiles_pre[[2]][nchar(CAMfiles_pre[[2]]$participantCAM) == 24,]
# CAMfiles_pre[[3]] <- CAMfiles_pre[[3]][nchar(CAMfiles_pre[[3]]$participantCAM.x) == 24,]
# number of CAMs collected
nrow(CAMfiles_pre[[1]])
[1] 719
# remove person who draw many empty concepts
# tmp_pid <- unique(CAMfiles_pre[[1]]$participantCAM[CAMfiles_pre[[1]]$CAM %in% c("a0c6edeb-267a-4f27-8199-79f896e033ce", "8d74f576-e617-4eb1-8ccf-93589ce6c65b")])
# print(tmp_pid)

## remove person from questionnaire data
# questionnaire <- questionnaire[!questionnaire$PROLIFIC_PID %in% tmp_pid,]

## remove person from CAM data
# table(CAMfiles_pre[[1]][CAMfiles_pre[[1]]$participantCAM %in% tmp_pid,]$text)
# CAMfiles_pre[[1]] <- CAMfiles_pre[[1]][!CAMfiles_pre[[1]]$participantCAM %in% tmp_pid,]
# CAMfiles_pre[[2]] <- CAMfiles_pre[[2]][!CAMfiles_pre[[2]]$participantCAM %in% tmp_pid,]
# CAMfiles_pre[[3]] <- CAMfiles_pre[[3]][!CAMfiles_pre[[3]]$participantCAM.x %in% tmp_pid,]


# remove 7 empty concepts:
# CAMfiles_pre[[1]]$text[nchar(CAMfiles_pre[[1]]$text) < 2]
# tmp_ids <- CAMfiles_pre[[1]]$id[nchar(CAMfiles_pre[[1]]$text) < 2]
# table(CAMfiles_pre[[1]]$isActive[CAMfiles_pre[[1]]$id %in% tmp_ids])
# table(CAMfiles_pre[[1]]$participantCAM[CAMfiles_pre[[1]]$id %in% tmp_ids])
# 
# CAMfiles_pre[[1]] <- CAMfiles_pre[[1]][!CAMfiles_pre[[1]]$id %in% tmp_ids,]




CAMfiles_pre[[1]]$text[CAMfiles_pre[[1]]$text == "Wissenschaft- Interesse"] <- "Wissenschaft-Interesse"
CAMfiles_pre[[1]]$text[CAMfiles_pre[[1]]$text == "BNE fächerbezogen"] <- "BNE-fächerbezogen"


### draw CAMs
CAMdrawn_pre <- draw_CAM(dat_merged = CAMfiles_pre[[3]],
                     dat_nodes = CAMfiles_pre[[1]],ids_CAMs = "all",
                     plot_CAM = FALSE,
                     useCoordinates = TRUE,
                     relvertexsize = 3,
                     reledgesize = 1)
processing 36 CAMs... 
Warning: `graph.data.frame()` was deprecated in igraph 2.0.0.
ℹ Please use `graph_from_data_frame()` instead.
Warning: `as.undirected()` was deprecated in igraph 2.1.0.
ℹ Please use `as_undirected()` instead.
[1] "== participantCAM in drawnCAM"
for(i in 1:length(CAMdrawn_pre)){
  if(any(nchar(V(CAMdrawn_pre[[i]])$label) < 3)){
    print(V(CAMdrawn_pre[[i]])$label)
  }
}
 [1] "Empirische Erkenntnisse zu meiner Didaktik"  
 [2] "Mein Bildungsauftrag"                        
 [3] "Meine Motivation für Nachhatligkeits Bildung"
 [4] "(Meine?) Verantwortung"                      
 [5] "Mein Wissenschaftinteresse"                  
 [6] "Werte hinter meiner Didaktik"                
 [7] "personalisierte Plattform"                   
 [8] "Gesellschaft und Soziales"                   
 [9] "Ökonomie"                                    
[10] "früh Bewusstsein schaffen "                  
[11] "Bildung des Weltbilds"                       
[12] "ja"                                          
[13] "aber"                                        
[14] "keine alleinige Verantwortung"               
[15] "Theorie "                                    
[16] "Ökologie"                                    
[17] "Wechselspiel der Verantwortung"              
[18] "verantwortliches Handeln"                    
[19] "eher"                                        
[20] "Altagsnähe schaffen"                         
### network indicators
tmp_microIndicator <- c("BNE", "BNE-fächerbezogen", "BNE Relevanz", "Empirische Fachdidaktik", "Wissenschaft-Interesse", "Verantwortung")
networkIndicators_pre <- compute_indicatorsCAM(drawn_CAM = CAMdrawn_pre, 
                                           micro_degree = tmp_microIndicator, 
                                           micro_valence = tmp_microIndicator, 
                                           micro_centr_clo = tmp_microIndicator, 
                                           micro_transitivity = tmp_microIndicator, 
                                           largestClique = FALSE)
Warning: `graph.density()` was deprecated in igraph 2.0.0.
ℹ Please use `edge_density()` instead.
Warning: The `types1` argument of `assortativity()` is deprecated as of igraph 1.6.0.
ℹ Please use the `values` argument instead.
Warning: `assortativity.degree()` was deprecated in igraph 2.0.0.
ℹ Please use `assortativity_degree()` instead.
### wordlist
CAMwordlist_pre <- create_wordlist(
  dat_nodes =  CAMfiles_pre[[1]],
  dat_merged =  CAMfiles_pre[[3]],
  useSummarized = TRUE,
  order = "frequency",
  splitByValence = FALSE,
  comments = TRUE,
  raterSubsetWords = NULL,
  rater = FALSE
)
[1] "create_wordlist - use raw words"
[1] 0
[1] 719
[1] "temporarily suffixes are added, because not all words have been summarized"
processing 36 CAMs... 
[1] "== participantCAM in drawnCAM"
if(all(nchar(CAMwordlist_pre$Words) > 2)){
  print("sucessfully removed empty words")
}

DT::datatable(CAMwordlist_pre, options = list(pageLength = 5)) 

save CAMs as .json files, and as .png (igraph)

if(save_CAMs_as_pictures){
setwd("outputs")

setwd("savedCAMs")
setwd("png")
### remove all files if there are any
if(length(list.files()) >= 1){
  file.remove(list.files())
  cat('\n!
      all former .png files have been deleted')
}

### if no participant ID was provided replace by randomly generated CAM ID

# if(all(CAMfiles_pre[[3]]$participantCAM.x == "noID")){
#   CAMfiles_pre[[3]]$participantCAM.x <- CAMfiles_pre[[3]]$CAM.x
# }

### save as .json files, and as .png (igraph)
ids_CAMs <- unique(CAMfiles_pre[[3]]$participantCAM.x); length(ids_CAMs)


for(i in 1:length(ids_CAMs)){
  save_graphic(filename = paste0("CAM", "_t1_", ids_CAMs[i])) #  paste0(ids_CAMs[i]))
  CAM_igraph <- CAMdrawn_pre[[c(1:length(CAMdrawn_pre))[
    names(CAMdrawn_pre) == paste0(unique(CAMfiles_pre[[3]]$participantCAM.x)[i])]]]
  plot(CAM_igraph, edge.arrow.size = .7,
       layout=layout_nicely, vertex.frame.color="black", asp = .5, margin = -0.1,
       vertex.size = 10, vertex.label.cex = .9)
  dev.off()
}

setwd("../json")
### remove all files if there are any
if(length(list.files()) >= 1){
  file.remove(list.files())
  cat('\n!
      all former .json files have been deleted')
}
for(i in 1:length(raw_CAM_pre)){
  if(!is_empty(raw_CAM_pre[[i]]$nodes)){
    if(nrow(raw_CAM_pre[[i]]$nodes) > 5){
      write(toJSON(raw_CAM_pre[[i]], encoding = "UTF-8"),
            paste0(raw_CAM_pre[[i]]$creator, ".json"))
    }
  }
}
}

!
      all former .png files have been deleted

!
      all former .json files have been deleted

merge and save all data

setwd("outputs/CAMs")


if(all(unique(CAMfiles_pre[[1]]$participantCAM) == networkIndicators_pre$participantCAM)){
    print("pre CAM ID can be set")
  networkIndicators_pre$CAM_ID <- unique(CAMfiles_pre[[1]]$CAM)
}
[1] "pre CAM ID can be set"
### remove all previously removed participants
nrow(networkIndicators_pre)
[1] 36
nrow(merged_data)
[1] 36
### match data
if (all(merged_data$PROLIFIC_PID == networkIndicators_pre$participantCAM)) {
  print("all data can be matched row by row")
  
  
  # fix IDs
  # networkIndicators_pre$participantCAM <- paste0(networkIndicators_pre$participantCAM, "_pre")

  
  # save questionnaire
  merged_data$participantCAM <- networkIndicators_pre$participantCAM

  ## save as .xlsx file
  xlsx::write.xlsx2(x = merged_data, file = "merged_data_final.xlsx")
  ## save as R object
  saveRDS(merged_data, file = "merged_data_final.rds")
  
  
  # save network indicators pre
  ## save as .xlsx file
  xlsx::write.xlsx2(x = networkIndicators_pre, file = "networkIndicators_pre_final.xlsx")
  ## save as R object
  saveRDS(networkIndicators_pre, file = "networkIndicators_pre_final.rds")
  
 
  
  # save CAMfiles pre
  saveRDS(CAMfiles_pre, file = "CAMfiles_pre_final.rds")
  
    # save CAMfiles combined and clean
  # saveRDS(CAMfiles_combined_translated, file = "CAMfiles_combined_final_translated.rds")
  
  # save questionnaire combined with CAMs
  # colnames(networkIndicators_pre) <- paste0(colnames(networkIndicators_pre), "_pre")

  merged_dataCAMs <- cbind(merged_data, networkIndicators_pre)
  dim(merged_dataCAMs)
  
  ## save as .xlsx file
  xlsx::write.xlsx2(x = merged_dataCAMs, file = "merged_dataCAMs_final.xlsx")
  ## save as R object
  saveRDS(merged_dataCAMs, file = "merged_dataCAMs_final.rds")
}
[1] "all data can be matched row by row"

describe sample

pupils who participated:

psych::describe(x = merged_dataCAMs[,c("sociodemo_age", "sociodemo_teaching_experience")])
                              vars  n  mean    sd median trimmed   mad min max
sociodemo_age                    1 36 34.03 12.53   32.5    33.3 15.57  18  60
sociodemo_teaching_experience    2 36  9.25 10.07    5.5     8.4  8.15   0  27
                              range skew kurtosis   se
sociodemo_age                    42 0.45    -1.30 2.09
sociodemo_teaching_experience    27 0.63    -1.19 1.68
table(merged_dataCAMs$sociodemo_gender)

female   male   none 
    30      5      1 
table(merged_dataCAMs$sociodemo_language)

yes 
 36 
table(merged_dataCAMs$sociodemo_subjects_taught)

                                                                 Biologie, Musik, Kath. Religion, Sport 
                                                                                                      1 
derzeit nur am Seminar mit Deutsch, zuvor alle Fächer in allen Klassenstufen (1-4) bereits unterrichtet 
                                                                                                      1 
                                                                                      Deutsch, Biologie 
                                                                                                      1 
                                                          Deutsch, Biologie, Kath. Religion, Informatik 
                                                                                                      1 
                                                                             Deutsch, Biologie, Technik 
                                                                                                      1 
                                                                             Deutsch, Geschichte, Sport 
                                                                                                      1 
                                                      Deutsch, Mathe, Sachunterricht, BSS, Kunst, Musik 
                                                                                                      1 
                                                             Deutsch, Mathe, soz. wiss. SU (Geschichte) 
                                                                                                      1 
                                                            Deutsch, naturw.-technischer Sachunterricht 
                                                                                                      1 
                                                        Deutsch, Naturwissenschaftlicher-Sachunterricht 
                                                                                                      1 
                                                       Deutsch, sozialwissenschaftlicher Sachunterricht 
                                                                                                      1 
                                                               Deutsch, Technik, Bildungswissenschaften 
                                                                                                      1 
                                                       Geographie, Biologie, Chemie, NwT, Medienbildung 
                                                                                                      1 
                                                                        Geographie, Deutsch, Geschichte 
                                                                                                      1 
                                                                                         Mathe Englisch 
                                                                                                      1 
                                                               Mathe, Deutsch, Englisch, Sachunterricht 
                                                                                                      1 
                                          Mathe, Naturwissenschaftlich-technischer Sachunterricht (AuG) 
                                                                                                      1 
                                                                         Mathe, Sachunterricht, Deutsch 
                                                                                                      1 
                 Mathematik und Sozialwissenschaftlicher Sachunterricht mit dem Schwerpunkt Geographie  
                                                                                                      1 
                                                          Mathematik, Deutsch, Biologie, DaZ/DaF, Ethik 
                                                                                                      1 
                                   Mathematik, Deutsch, Englisch, Sachunterricht, evangelische Religion 
                                                                                                      1 
                                                                     Mathematik, Deutsch, ev. Theologie 
                                                                                                      1 
                                  Mathematik, Deutsch, Sachkunde, Kunst und Werken, Musik, ev. Religion 
                                                                                                      1 
                                                     Mathematik, ev. Religion, Sachunterricht, Englisch 
                                                                                                      1 
                                                                                 Mathematik, Geographie 
                                                                                                      2 
                                                     Mathematik, naturwissenschaftlichen Sachunterricht 
                                                                                                      1 
                                         Mathematik, Naturwissenschaftlicher-Technischer Sachunterricht 
                                                                                                      1 
                                                     Mathematik, naturwissenschaftlicher Sachunterricht 
                                                                                                      1 
                                                                                       Mathematik, NWSU 
                                                                                                      1 
                                                    Mathematik, Sozialwissenschaftlicher Sachunterricht 
                                                                                                      1 
                                                                            Mathematik, Sport, Biologie 
                                                                                                      1 
                                                   Religion, Mathematik, Deutsch, Sachunterricht, Kunst 
                                                                                                      1 
                                                                              Sachunterricht, Pädagogik 
                                                                                                      1 
                                                                                                  Sport 
                                                                                                      1 
                                                                                             Test, Test 
                                                                                                      1 
table(merged_dataCAMs$sociodemo_school_types)

                                                       GMS 
                                                         1 
                                               Grundschule 
                                                        17 
                                                 Gymnasium 
                                                         1 
                                              Primarschule 
                                                         1 
                                               Primarstufe 
                                                         8 
                                                Realschule 
                                                         4 
                             Realschule und Werkrealschule 
                                                         1 
                                                Test, Test 
                                                         1 
                                      Werkreal-/Realschule 
                                                         1 
Zur Zeit gar nicht, da ich voll am Semianr beschäftigt bin 
                                                         1 
table(merged_dataCAMs$sociodemo_teaching_experience)

 0  1  2  3  4  7  8 10 14 15 16 20 21 23 26 27 
12  1  3  1  1  1  1  4  1  1  1  1  2  1  1  4 

CAMs:

psych::describe(x = networkIndicators_pre[,c("mean_valence_macro", "num_nodes_macro", "num_edges_macro")])
                   vars  n  mean    sd median trimmed   mad   min   max range
mean_valence_macro    1 36  1.01  0.69   0.86    0.99  0.58 -0.17  2.67  2.83
num_nodes_macro       2 36 19.94  7.64  18.00   19.23  7.41 12.00 40.00 28.00
num_edges_macro       3 36 30.17 17.08  26.00   28.13 11.86 12.00 99.00 87.00
                   skew kurtosis   se
mean_valence_macro 0.43    -0.49 0.11
num_nodes_macro    0.73    -0.56 1.27
num_edges_macro    1.89     4.88 2.85

References

Peng, Roger D., and Elizabeth Matsui. 2016. The Art of Data Science: A Guide for Anyone Who Works with Data. Lulu.com. https://bookdown.org/rdpeng/artofdatascience/.
Wickham, Hadley, and Garrett Grolemund. 2017. R for Data Science: Import, Tidy, Transform, Visualize, and Model Data. "O’Reilly Media, Inc.". https://r4ds.had.co.nz/.
Xie, Yihui, J. J. Allaire, and Garrett Grolemund. 2018. R Markdown: The Definitive Guide. New York: Chapman; Hall/CRC. https://doi.org/10.1201/9781138359444.