<<<<<<< Updated upstream:RCode/collaboration/oxcgrt/oxcgrt_coronanet_taxonomy.html ======= >>>>>>> Stashed changes:RCode/collaboration/covidamp/COVIDAMP_coronanet_taxonomy.html OxCGRT - CoronaNet Taxonomy Map

OxCGRT - CoronaNet Taxonomy Map

0 Introduction

This document maps the Oxford Covid-19 Government Response Tracker (OxCGRT) taxonomy used to document government policies made in response to COVID-19 into the CoronaNet taxonomy. Each section maps the general area for which the taxonomy is mapped and each sub-section provides further detail as necessary. Following each explanation for how the mapping is conceptualized, there is R code for operationalizing this mapping. Please refer to the OxCGRT Documentation accessible through their github and the CoronaNet Codebook for more information on their respective taxonomies.

Note that the code below is customized to adjust for errors and idiosyncrasies in the OxCGRT data as of September 10, 2021. You can access (i) this original version of the OxCGRT dataset, “OxCGRT_latest_withnotes.csv” as well as (ii) the version which transforms this version of the OxCGRT dataset into the CoronaNet taxonomy “ox_coronanet_map.csv.gz” (the rest of this document details how this transformation was implemented) from the CoronaNet pubic git repo.


1 Setup

To create replicate this taxonomy mapping exercise, users will need to load the following R packages and to read in the original OxCGRT data.

# load packages
library(readr)
library(magrittr)
<<<<<<< Updated upstream:RCode/collaboration/oxcgrt/oxcgrt_coronanet_taxonomy.html
library(dplyr)
library(tidyr)
library(lubridate)
library(stringr)
library(here)

# read in data
ox_notes = read.csv(here("data", "collaboration", "oxcgrt", "OxCGRT_latest_withnotes.csv"), na.strings=c("","NA"))
colnames(ox_notes) = gsub('\\.', ' ', colnames(ox_notes))

# string to match urls
url_pattern <- "http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\\(\\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+"

2 Data Preparation

2.1 One-to-one mappings

The following code identifies the variables for which there is a one-to-one relationship between the OxCGRT data and the CoronaNet taxonomy.

  • Becauase the OxCGRT data does not itself possess unique ids to track different policies, we create one for them. We create this ox_id by pasting the following variables together:

    • The name of the country a policy originates from (from the CountryName variable)
    • If available the region within the country is used (from the RegionName variable)
    • and the start date of the policy and putting them together (from the Date variable)
    • An example of an id that does not have any region information associated with it would be ‘Aruba_20200310’.
  • ox_id_num is added as an additional identifying feature of a policy by using the row number the policy is stored in.

  • OxCGRT’s CountryName variable and CountryCode variable, which capture the name and ISO code of the initiating country, are perfect matches for Coronanet’s country variable and ISO_A3 variable. However not, because OxCGRT and CoronaNet consider a number of countries differently in terms of sovereignty a few of the ISO_A3 codes have to be adjusted.

    • E.g. Guam is consisdered a province in the CoronaNet dataset as opposed to a country in the OxCGRT dataset. It is therefore assigned USA as ISO_A3 code to reflect its status as a province in the CoronaNet dataset. The same is true of Puerto Rico and the U.S. Virgin Islands.
  • OxCGRT’s Region variable and RegionCode variable, which captures information on the initiating ISO level 2, are perfect matches for Coronanet’s province variable and ISO_L2 variable.

  • OxCGRT’s Jurisdiction variable captures information on the level of government initiating a policy, which matches CoronaNet’s init_country_level variable and can therefore be mapped as is.

ox_notes = ox_notes %>% 
  mutate(ox_id = ifelse(
    is.na(RegionName), paste(CountryName, Date, sep = '_'), paste(CountryName, RegionName, Date, sep  = '_')
  )
  )
ox_notes$ox_id_num  = seq.int(nrow(ox_notes))
types = c(
  'C1_School closing',
  'C2_Workplace closing',
  'C3_Cancel public events',
  'C4_Restrictions on gatherings',
  'C5_Close public transport',
  'C6_Stay at home requirements',
  'C7_Restrictions on internal movement',
  'C8_International travel controls',
  'H1_Public information campaigns',
  'H2_Testing policy',
  'H3_Contact tracing',
  'H4_Emergency investment in healthcare',
  'H5_Investment in vaccines',
  'H6_Facial Coverings',
  'H7_Vaccination policy',
  'H8_Protection of elderly people'
)
ox2coronanet = ox_notes %>%
  # remove empty rows
  mutate(dum = rowSums(across(types), na.rm = TRUE)) %>%
  filter(dum != 0)  %>%
  # convert dates
  mutate(Date = ymd(Date)) %>%
  # convert geographic names
  mutate(country = 
           case_when(
             CountryCode == "GUM" ~ "United States",
             CountryCode == "PRI" ~ "United States",
             CountryCode == "VIR" ~ "United States",
             TRUE ~      CountryName
           ),
         
         province = 
           case_when(
             CountryCode == "GUM" ~ "Guam",
             CountryCode == "PRI" ~ "Puerto Rico",
             CountryCode == "VIR" ~ "United States Virgin Islands",
             TRUE ~ RegionName
           ),
         ISO_A3 = case_when(
           # CountryCode == "ABW" ~ "NLD",
           # CountryCode == "BMU" ~ "GBR",
           #  CountryCode == "FRO" ~ "DNK",
           #  CountryCode == "GRL" ~ "DNK",
           CountryCode == "GUM" ~ "USA",
           CountryCode == "PRI" ~ "USA",
           CountryCode == "VIR" ~ "USA",
           CountryCode == "RKS" ~ "XKX",
           TRUE ~ CountryCode),
         ISO_L2 = RegionCode,
         init_country_level = 
           case_when(
             province == "Guam"~ 'Provincial',
             province == "Puerto Rico"~ 'Provincial',
             province == "United States Virgin Islands"~ 'Provincial',
             Jurisdiction == 'NAT_TOTAL' ~ 'National',
             Jurisdiction == 'STATE_TOTAL'~'Provincial', 
             TRUE ~ as.character(NA)) )
======= library(tidyr) library(stringr) library(readxl) library(here) # original data covidamp = read_excel( here("data", "collaboration", "covidamp", "COVID AMP - Data Export 2021-09-10.xlsx" ), skip = 6 , sheet = "Policies") # clean column names colnames(covidamp) = gsub("\\s*\\([^\\)]+\\)","",as.character(colnames(covidamp))) colnames(covidamp) = gsub('[[:punct:] ]+',' ', colnames(covidamp)) colnames(covidamp) = gsub(' ', '_', colnames(covidamp)) for (i in 1:ncol(covidamp)) { temp = covidamp[1,i, drop = T] if (class(temp) == "Date") { next } covidamp[,i] = replace(covidamp[,i], covidamp[,i] == "N/A", NA) covidamp[,i] = replace(covidamp[,i], covidamp[,i] == "", NA) } colnames(covidamp)[1] = "unique_id" # prediction data amp_predicts = read_csv( here("data", "collaboration", "covidamp", "amp_predict.csv"))
>>>>>>> Stashed changes:RCode/collaboration/covidamp/COVIDAMP_coronanet_taxonomy.html


3 Policy Types

Because the OxCGRT data is formatted in a times series format, as opposed to an event dataset format as is true of CoronaNet and the other datasets that are part of this broader harmonization exercise, we employed a different procedure to map the policy types captured in OxCGRT to the CoronaNet taxonomy. The basic idea of the mapping process was to create a clean data frame for each policy type and then to combine them in the end. To that end, for each policy type available in the OxCGRT taxonomy, we do the following:

  1. Strip down the data to only the essential variables that can be used without any changes to them. See sections below on ‘filter_w_flag’ and ‘filter_wo_flag’ functions below for more information.
  2. Add as many additional variables as possible by mutating existing ones or creating new ones based on the information available.
  3. Use the ‘filter_no_changes’ and ‘filter_same_description’ to reduce the number of policies down to the ones that imply changes. See the sections below on these functions for more information on what they do.
  4. Create a unique id by combining the policy type and ox_id, e.g. ‘Aruba_20200316_school’ that identifies only one policy in the OxCGRT dataset.
  5. Mutate ox_id to be the combination of ox_id_num and the type of policy, e.g. ‘100_school’
  6. Combine all the data frames at the end of the mapping process.

3.1 Filter Functions

3.1.1 Filter with XX_Flag variables

Note that ‘XX’ is a stand in for a given OxCGRT indicator, e.g. ‘E1_flag’ are economic policies, and ‘H1_flag’ health system policies.

The following code creates a function to process a given ‘XX’ OxCGRT indicators from a panel dataset form into an event datset form. For each OxCGRT indicator with a flag, the ‘filter_w_flag’ function extracts information from the Flag for that indicator, XX_Flag, as well as the Notes field for that indicator, XX_Notes. Note that the Flag for a given indicator can either note a demographic or geographic distinction in the policy-making process. Note, however, not all indicators in the OxCGRT dataset have a flag value and thus another function (see below), filter_wo_flag, was created to subset every policy type and clean it for these cases. The following explains in greater detail how the filter_w_flag function works:

  1. Filter to only rows relevant to the chosen category are selected (note that in order to select the appropriate rows the pasted String needs to be transformed into a variable, hence the ‘get’).
    • filter(!is.na(get(paste(String))) & !is.na(get(paste(substr(String, 1, 3), "Notes", sep = "")))
  2. Select only columns relevant to the chosen category. This is done to save some computing time as there are a couple hundred columns of information that are not needed.
    • select(ox_id, ox_id_num, country, ISO_A3, province, ISO_L2, init_country_level, Date, paste(String), paste(substr(String, 1, 3), "Notes", sep = ""), paste(substr(String, 1, 3), "Flag", sep = "")).
  3. Extract information on the end date of a policy from Oxford’s Date variable and store it in date_end in the CoronaNet taxonomy.
    • mutate(date_end = c(lead(as.character(Date)))).
  4. Map OxCGRT’s country variable to CoronaNet’s target_country variable.
    • It is always assumed that the target country of a policy is the same as the initiating country.
  5. Extract information on the start date of a policy from Oxford’s Date variable and store it in date_start in the CoronaNet taxonomy.
    • date_start = Date.
  6. Save the OxCGRT information on the policy XX_Notes in the CoronaNet variable description.
    • description = get(paste(substr(String, 1, 3), “Notes”, sep = "")).
  7. Map OxCGRT’s XX_Flag dummy variable to CoronaNet’s target_geog_level variable.
    • When XX_Flag is 1, the target_geog_level in the CoronaNet taxonomy takes the value of: “One or more countries, but not all countries”.
  8. Finally, the data frame is trimmed to include only the necessary columns and returned to the global environment as temp.
    • select(-Date, -paste(substr(String, 1, 3), “Notes”, sep = "“), -paste(substr(String, 1, 3),”Flag“, sep =”")).
    • .GlobalEnv$temp = temp
         filter_w_flag = function(String) {
           temp = ox2coronanet %>%
             filter(
               !is.na(get(paste(String))) & !is.na(get(paste(substr(String, 1, 3), "Notes", sep = "")))
             ) %>%
             select(
               ox_id,
               ox_id_num,
               country,
               ISO_A3,
               province,
               ISO_L2,
               init_country_level,
               Date,
               paste(String),
               paste(substr(String, 1, 3), "Notes", sep = ""),
               paste(substr(String, 1, 3), "Flag", sep = ""),
             ) %>%
             group_by(country, province) %>%
             mutate(
               date_end = c(lead(as.character(Date)))
             ) %>%
             ungroup() %>%
             mutate(
               target_country =
                 case_when(
                   province == "Guam"~ "United States",
                   province == "Puerto Rico"~ "United States",
                   province == "United States Virgin Islands"~ "United States",
                   TRUE ~  country
                 ) ,
               target_province =
                 case_when(
                   province == "Guam"~ "Guam",
                   province == "Puerto Rico"~ "Puerto Rico",
                   province == "United States Virgin Islands"~ "United States Virgin Islands",
                   TRUE~as.character(NA)
                 ),
               date_start = Date,
               link = str_extract(get(paste(substr(String, 1, 3), "Notes", sep = "")), url_pattern),
               description = get(paste(substr(String, 1, 3), "Notes", sep = "")),
               description = get(paste(substr(String, 1, 3), "Notes", sep = "")),
               description_nourl=  sub("Link:.*$", '',  description),
               description_nourl  =  sub("link:.*$", '',  description_nourl),
               description_nourl =  sub("Source:.*$", '',  description_nourl),
               description_nourl =  sub("source:.*$", '',  description_nourl),
               description_nourl = gsub(url_pattern, '', description_nourl),
               description_nourl =gsub("policy stays the same as|See previous coding review|Coding review:|lease refer to the note|please refer to the", "", description_nourl),
               count = nchar(description_nourl),
               target_geog_level =
                 ifelse(
                   get(paste(substr(String, 1, 3), "Flag", sep = "")) == 1,
                   "One or more countries, but not all countries",
                   "One or more provinces within a country"
                 )
             ) %>%
             select(-Date, -paste(substr(String, 1, 3), "Notes", sep = ""), -paste(substr(String, 1, 3), "Flag", sep = ""))
           .GlobalEnv$temp  = temp
         }


3.1.3 Filter without XX_Flag variables

The following code creates a function to process a given ‘XX’ OxCGRT indicators from a panel dataset form into an event datset form. For each OxCGRT indicator without a flag, the ‘filter_wo_flag’ function extracts information from the Notes field for that indicator, XX_Notes.T Note, however, some indicators in the OxCGRT dataset have a flag value and thus another function (see above), filter_w_flag, was created to subset every policy type and clean it for these cases. The following explains in greater detail how the filter_wo_flag function works:

  1. Filter to only rows relevant to the chosen category are selected (note that to select the appropriate rows the pasted String needs to be transformed into a variable, hence the ‘get’).
    • filter(!is.na(get(paste(String))) & !is.na(get(paste(substr(String, 1, 3), "Notes", sep = ""))).
  2. Select only columns relevant to the chosen category.
    • select(ox_id, ox_id_num, country, ISO_A3, province, ISO_L2, init_country_level, Date, paste(String), paste(substr(String, 1, 3), "Notes", sep = ""), paste(substr(String, 1, 3), "Flag", sep = "")).
  3. Extract information on the end date of a policy from Oxford’s Date variable and store it in date_end in the CoronaNet taxonomy.
    • mutate(date_end = c(lead(as.character(Date)))).
  4. Map OxCGRT’s country variable to CoronaNet’s target_country variable
    • It is always assumed that the target country of a policy is the same as the initiating country.
  5. Extract information on the start date of a policy from Oxford’s Date variable and store it in date_start in the CoronaNet taxonomy.
    • date_start = Date.
  6. Save the OxCGRT information on the policy XX_Notes in the CoronaNet variable description.
    • description = get(paste(substr(String, 1, 3), “Notes”, sep = "")).
  7. Finally the data frame is trimmed to include only the necessary columns and returned to the global environment as temp.
    • select(-Date, -paste(substr(String, 1, 3), “Notes”, sep = "“), -paste(substr(String, 1, 3),”Flag“, sep =”")).
    • .GlobalEnv$temp = temp.
                  filter_wo_flag = function(String) {
                    temp = ox2coronanet %>%
                      filter(
                        !is.na(get(paste(String))) & !is.na(get(paste(substr(String, 1, 3), "Notes", sep = "")))
                      ) %>%
                      select(
                        ox_id,
                        ox_id_num,
                        country,
                        ISO_A3,
                        province,
                        ISO_L2,
                        init_country_level,
                        Date,
                        paste(String),
                        paste(substr(String, 1, 3), "Notes", sep = ""),
                      ) %>%
                      group_by(country, province) %>%
                      mutate(
                        date_end = c(lead(as.character(Date)))
                      ) %>%
                      ungroup() %>%
                      mutate(
                        target_country = country,
                        date_start = Date,
                        description = get(paste(substr(String, 1, 3), "Notes", sep = "")),
                        link = str_extract(get(paste(substr(String, 1, 3), "Notes", sep = "")), url_pattern),
                        description_nourl=  sub("Link:.*$", '',  description),
                        description_nourl  =  sub("link:.*$", '',  description_nourl),
                        description_nourl =  sub("Source:.*$", '',  description_nourl),
                        description_nourl =  sub("source:.*$", '',  description_nourl),
                        description_nourl = gsub(url_pattern, '', description_nourl),
                        description_nourl = ifelse(is.na(link), gsub("See previous coding review|Coding review:|lease refer to the note|please refer to the", "", description_nourl), description_nourl),
                        count = nchar(description_nourl),
                      ) %>%
                      select(-Date, -paste(substr(String, 1, 3), "Notes", sep = ""))
                    .GlobalEnv$temp  = temp
                  }


3.2 Description filter functions

  • A filter_no_changes function is created, which filters for policy descriptions that indicate no change in the status quo. This function is used throughout the mapping process to reduce the number of duplicate policies as much as possible.
  • A filter_same_description function is created, which filters for identical policy descriptions. This function is used throughout the mapping process to reduce the number of duplicate policies as much as possible.
                  filt_patterns= function(data){
                    no_change_patt =   data %>%
                      arrange(count) %>%
                      filter(count < 100)%>%
                      mutate(description_nourl = str_trim(description_nourl))%>%
                      mutate(description_nourl = str_replace_all(description_nourl, "[[:punct:]]", ""))%>%
                      mutate(description_nourl = str_trim(description_nourl))%>%
                      filter((count < 35 & grepl("No changing in previous policies|No change in policy|Policy is still in effect|No measures|No change|Restrictions remain largely unchanged|No policy change|No measures were found|No explicit new measures found|No Evidence of Policy|no such measure|Same directives as earlier|Same as before|The previous note is still valid|Still active|No new restriction|The same as|No policies found|No information was found|No New Policy identified|No available data|no policy change|No details found|No new information|No new policy|no new policy|No policy|no policy|announce|no new|update|Update|Change|change|No guidance|no guidance|Nothing|No info available|Nothing to suggest any policy in place|No Policy|Still current|No policy update|No new measure|No measures|No evidence of a policy change|No evidence of policy change|No data|No specific policy mentioned|still in place|No evidence of a policy change|No evidence of policy change|No major changes noted|No concrete restriction|no data available|No information found|No change|No change|No restriction|NO POLICY CHANGE|Remains as per the previous note|No improvment found|remains the same|remain the same|Same as above|Same policy|No policies in place|No new guidance|No new policies|Same as last|no data|No  new policy|No new polic|no measure|No measure|Previous policy continues|Previous policy is continued", description_nourl))|
                               (count < 41 & grepl("No relevant update|There are no restrictions|No further evidence of|No new changes in the policy post|No specific measures could be found|No major changes noted since|Previous policies are still in force", description_nourl))|
                               (count < 60 & grepl("I was unable to find any|I do not find any|I was unable to find any|did not find any|Unable to find anything specific", description_nourl))|
                               description_nourl %in% c(
                                 "I did not find additional information",
                                 "No additional policy information found",
                                 "No new policy or change in policy identified",
                                 "No improvement found",
                                 "I wasn't able to find any measure in place",
                                 "No specific protection measures could be found",
                                 "There is no mention of measures concerning this",
                                 "No detected change in this indicator",
                                 "After a search of provincial sites and news sites, there are no updates to this indicator",
                                 "No new specific measures to protect the elderly announced",
                                 "Cannot find anythign to indicate this policy has changed",
                                 "annot find any specific measures for the elderly",
                                 "No policies related to the protection of elderly people",
                                 "No particular policy on the protection of elderly people",
                                 "No mention of extra protections for elderly people beyond the restrictions"
                               )
                      ) %>%
                      select(description_nourl) %>%
                      distinct %>%
                      mutate(
                        change_pattern =
                          paste(description_nourl, collapse = '|')) %>%
                      select(change_pattern) %>% distinct %>% pull
                    .GlobalEnv$no_change_patt = no_change_patt
                  }
                  filter_no_changes = function(data){
                    data =  do.call(rbind, lapply(unique(data$country), function(c){
                      slice = data %>% filter(country == c) %>% data.frame
                      slice = slice %>%
                        mutate(description_nourl_raw = str_trim(description_nourl),
                               description_nourl_raw = str_replace_all(description_nourl_raw, "[[:punct:]]", ""),
                               count_raw = nchar(description_nourl_raw))
                      last_row = slice %>% slice(n())
                      slice = slice %>%
                        slice(1:c(n()-1))
                      slice  = slice [!(grepl(no_change_patt, slice$description_nourl_raw)  & slice$count_raw < 80 ),]
                      slice = rbind(slice, last_row)
                    }))
                  }
                  filter_same_description = function(data){
                    data =  do.call(rbind, lapply(unique(data$country), function(c){
                      slice = data %>% filter(country == c) %>% data.frame
                      slice = slice %>%
                        mutate(description_nourl_raw = str_trim(description_nourl),
                               description_nourl_raw = str_replace_all(description_nourl_raw, "[[:punct:]]", ""),
                               count_raw = nchar(description_nourl_raw),
                               short_desc_dum = ifelse(count_raw < 20, 1, 0),
                               only_url_dum = ifelse(description_nourl_raw == '', 1, 0)
                        )
                      slice_save = slice %>% filter(short_desc_dum == 1  )
                      slice_filt = slice %>%
                        filter(short_desc_dum==0 ) %>%
                        group_by(description_nourl_raw ) %>%
                        slice(c(1,n())) %>%
                        ungroup() %>% distinct
                      slice = rbind(slice_filt,slice_save) %>%
                        arrange(date_start)
                      return(slice )
                    }))
                  }


3.2 School closure policies

The OxCGRT C1_Closing school variable is semantically similar to CoronaNet’s Closure and Regulation of Schools policy type, and type_sub_cat. The following code maps the former to the latter. Note that we can also extract information for CoronaNet’s institution_status variable, which records whether an institution is closed, open or open with conditions.

  • OxCGRT’s C1_Closing school’s ordinal values to CoronaNet’s compliance variable
    • When C1_School closing takes on the values of 2 or 3, this is equivalent to a ‘Mandatory (Unspecified)’ compliance in the CoronaNet taxonomy
  • OxCGRT’s C1_Closing school’s ordinal values to CoronaNet’s type_sub_cat variable
    • When C1_School closing takes on the value 3, this is equivalent to all relevant sub-types for ‘Closure and Regulation of Schools’
  • OxCGRT’s C1_School’s variable and CoronaNet’s institutions_status variable
    • When C1_School closing takes the value of 0, CoronaNet’s institution_status variable takes the value of ’allowed to open with no conditions" for a given sub-type.
    • When C1_School closing takes the value of 1, 2, or 3, CoronaNet’s institution_status variable takes the value of “closed/locked down” for a given sub-type.
                  filter_w_flag("C1_School closing")
                  ox2coronanet_schools = temp %>%
                    mutate(
                      compliance =
                        ifelse(
                          `C1_School closing` %in% c(2, 3),
                          "Mandatory (Unspecified)",
                          NA
                        ),
                      type = 'Closure and Regulation of Schools',
                      unique_id = paste(ox_id, "school", sep = "_"),
                      ox_id = paste(ox_id_num, "school", sep = "_"),
                      type_sub_cat =
                        ifelse(
                          `C1_School closing` == 3,
                          'Preschool or childcare facilities (generally for children ages 5 and below),Primary Schools (generally for children ages 10 and below),Secondary Schools (generally for children ages 10 to 18),Higher education institutions (i.e. degree granting institutions)',
                          NA
                        ),
                      institution_status =
                        ifelse(
                          `C1_School closing` == 0,
                          paste0(type_sub_cat, " allowed to open with no conditions"),
                          ifelse(
                            `C1_School closing` %in% c(1, 2, 3),
                            #`C1_School closing` == 3,
                            paste0(type_sub_cat, " closed/locked down"),
                            NA
                          )
                        )
                    ) %>%
                    select(-"C1_School closing")
                  filt_patterns(ox2coronanet_schools)
                  ox2coronanet_schools = filter_no_changes(ox2coronanet_schools)
                  ox2coronanet_schools = filter_same_description(ox2coronanet_schools)


3.3 Workplace closing

The OxCGRT Workplace closing variable is structurally difficult to map to the CoronaNet taxonomy because CoronaNet differentiates between government workplaces and private workplaces, whereas the Workplace closing does not. In the following, we assume that all data coded as Workplace closing can be mapped to private workplaces, which CoronaNet documents in its Restriction and Regulation of Businesses policy type. The manual harmonisation phase will identify observations in which case-by-case changes to other policy types will need to be made.

  • OxCGRT’s C2_Workplace closing’s ordinal values to CoronaNet’s compliance variable.
    • When C2_Workplace closing takes on the values of 2 and 3, this is equivalent to a ‘Mandatory (Unspecified)’ compliance in the CoronaNet taxonomy.
    • Although OxCGRT does differentiate between essential and non-essential businesses, the distinction is different from CoronaNet’s and is therefore ignored.
    • Filtering out the different businesses that are closed would potentially be possible but is not worth it considering the time it would take and the minor details it would bring.
                  filter_w_flag("C2_Workplace closing")
                  ox2coronanet_rest_business = temp %>%
                    mutate(
                      type = 'Restriction and Regulation of Businesses',
                      unique_id = paste(ox_id, "workplace", sep = "_"),
                      ox_id = paste(ox_id_num, "workplace", sep = "_"),
                      compliance = case_when(
                        `C2_Workplace closing` == 1 ~ "Voluntary/Recommended but No Penalties",
                        `C2_Workplace closing` %in% c(2,3) ~ "Mandatory (Unspecified)",
                        TRUE ~ as.character(NA)
                      )
                    ) %>%
                    select(-"C2_Workplace closing")
                  filt_patterns(ox2coronanet_rest_business )
                  ox2coronanet_rest_business  = filter_no_changes(ox2coronanet_rest_business )
                  ox2coronanet_rest_business = filter_same_description(ox2coronanet_rest_business)


3.4 Cancel public events

The OxCGRT C3_Cancel public events variable is semantically similar to CoronaNet’s Restrictions of Mass Gatherings policy type. However, because OxCGRT does not systematically differentiate between different types of public events, it is not possible to further differentiate and capture these in CoronaNet’s type_sub_cat variable, which is where the CoronaNet taxonomy makes such distinctions.

  • OxCGRT’s C3_Cancel public events’s ordinal values to CoronaNet’s compliance variable.
  • When C3_Cancel public events takes on the values of 2, this is equivalent to a ‘Mandatory (Unspecified)’ compliance in the CoronaNet taxonomy.
  • Filtering out the type of public event is possible through the textual notes provided by the OxCGRT dataset, but given that this information is not standardized, we came to the conlusion that it would not be possibly to systematically sift this information through an algorithm. The manual harmonisation phase will identify observations in which case-by-case changes to other policy types will need to be made.
filter_w_flag("C3_Cancel public events")
ox2coronanet_pub_events = temp %>%
  mutate(
    type = 'Restrictions of Mass Gatherings',
    unique_id = paste(ox_id, "events", sep = "_"),
    ox_id = paste(ox_id_num, "events", sep = "_"),
    compliance = case_when(
      `C3_Cancel public events` == 1 ~ "Voluntary/Recommended but No Penalties",
      `C3_Cancel public events` == 2 ~ "Mandatory (Unspecified)",
      TRUE ~ as.character(NA)
    )
  ) %>%
  select(-"C3_Cancel public events")
filt_patterns(ox2coronanet_pub_events )
ox2coronanet_pub_events  = filter_no_changes(ox2coronanet_pub_events)
ox2coronanet_pub_events = filter_same_description(ox2coronanet_pub_events)


3.5 Restrictions on gatherings

The OxCGRT C4_Restrictions on gatherings variable is semantically similar to CoronaNet’s Restrictions of Mass Gatherings policy type.

Note that OxCGRT splits up the policies regarding the limitation of group sizes into four categories: ‘0-10’, ‘10-100’, ‘101-1000’, ‘1000+’. These categories of different group sizes are mapped to CoronaNet’s variable type_mass_gathering with their upper limit being the restriction in the CoronaNet taxonomy. 1000+ limit would be a regular Restrictions of Mass Gatherings with no specified limit.

filter_w_flag("C4_Restrictions on gatherings")
ox2coronanet_gatherings = temp %>%
  mutate(
    type = 'Restrictions of Mass Gatherings',
    unique_id = paste(ox_id, "gatherings", sep = "_"),
   ox_id = paste(ox_id_num, "gatherings", sep = "_"),
    type_mass_gathering = case_when(
      `C4_Restrictions on gatherings` == 2 ~ "1000",
      `C4_Restrictions on gatherings` == 3 ~ "100",
      `C4_Restrictions on gatherings` == 4 ~ "10",
      TRUE ~ as.character(NA)
    )
  ) %>%
  select(-"C4_Restrictions on gatherings")
filt_patterns(ox2coronanet_gatherings)
ox2coronanet_gatherings = filter_no_changes(ox2coronanet_gatherings)
ox2coronanet_gatherings = filter_same_description(ox2coronanet_gatherings)


3.6 Close public transport

OxCGRT’s ‘C5_Close public transport’ policies are a perfect fit for CoronaNet’s Social Distancing category.

filter_w_flag("C5_Close public transport")
ox2coronanet_pub_transport = temp %>%
  mutate(
    type = 'Social Distancing',
    unique_id = paste(ox_id, "transport", sep = "_"),
    ox_id = paste(ox_id_num, "transport", sep = "_")
  ) %>%
  select(-"C5_Close public transport")
filt_patterns(ox2coronanet_pub_transport)
ox2coronanet_pub_transport = filter_no_changes(ox2coronanet_pub_transport)
ox2coronanet_pub_transport = filter_same_description(ox2coronanet_pub_transport)


3.7 Stay-at-home requirements

OxCGRT’s ‘C6_Stay at home requirements’ policies are a perfect fit for CoronaNet’s Lockdown category.

  • OxCGRT’s C6_Stay at home requirements’ ordinal values to CoronaNet’s compliance variable
    • When C6_Stay at home requirements takes on the values of 2 or 3, this is equivalent to a ‘Mandatory (Unspecified)’ compliance in the CoronaNet taxonomy.
                  filter_w_flag("C6_Stay at home requirements")
                  ox2coronanet_stay_home = temp %>%
                    mutate(
                      type = 'Lockdown',
                      unique_id = paste(ox_id, "stay", sep = "_"),
                      ox_id = paste(ox_id_num, "stay", sep = "_"),
                      compliance = case_when(
                        `C6_Stay at home requirements` == 1 ~ "Voluntary/Recommended but No Penalties",
                        `C6_Stay at home requirements` %in% c(2, 3) ~ "Mandatory (Unspecified)",
                        TRUE ~ as.character(NA)
                      )
                    ) %>%
                    select(-"C6_Stay at home requirements")
                  filt_patterns(ox2coronanet_stay_home)
                  ox2coronanet_stay_home = filter_no_changes(ox2coronanet_stay_home)
                  ox2coronanet_stay_home = filter_same_description(ox2coronanet_stay_home)


3.8 Restrictions on internal movement

  • OxCGRT’s C7_Restrictions on internal movements’ ordinal values to CoronaNet’s compliance variable
    • When C7_Restrictions on internal movement takes on the values of 2, this is equivalent to a ‘Mandatory (Unspecified)’ compliance in the CoronaNet taxonomy
filter_w_flag("C7_Restrictions on internal movement")
ox2coronanet_int_mvt = temp %>%
  mutate(
    type = 'Internal Border Restrictions',
    unique_id = paste(ox_id, "intmvt", sep = "_"),
    ox_id = paste(ox_id_num, "intmvt", sep = "_"),
    compliance = case_when(
      `C7_Restrictions on internal movement` == 1 ~ "Voluntary/Recommended but No Penalties",
      `C7_Restrictions on internal movement` == 2 ~ "Mandatory (Unspecified)",
      TRUE ~ as.character(NA)
    )
  ) %>%
  select(-"C7_Restrictions on internal movement")
filt_patterns(ox2coronanet_int_mvt)
ox2coronanet_int_mvt = filter_no_changes(ox2coronanet_int_mvt)
ox2coronanet_int_mvt = filter_same_description(ox2coronanet_int_mvt)


3.9 International travel controls

  • OxCGRT’s ‘C8_International travel controls’ are concerned with external borders and therfore a perfect match for CoronaNet’s External Border Restrictions. An exception to this is when the ordinal value for this indicator is 2, which indicates that some arrivals have to quarantine. In such cases, these policies are coded as Quarantine in the CoronaNet taxonomy.

  • Depending on the ordinale value of C8_International travel controls, CoronaNets subcategories are either Health Screening (2) or a Total border crossing ban (3,4).

filter_wo_flag("C8_International travel controls")
ox2coronanet_ext_border = temp %>%
  mutate(
    type = case_when(
      `C8_International travel controls` == 2 ~ "Quarantine",
      `C8_International travel controls` %in% c(0,1,3,4) ~ "External Border Restrictions",
      TRUE ~ as.character(NA)
    ),
    type_sub_cat = case_when( # TODO Wrong subcategory name but which one do I use?
      `C8_International travel controls` == 1 ~ "Health Screenings",
      `C8_International travel controls` %in% c(3, 4) ~ "Total border crossing ban"
    ),
    unique_id = paste(ox_id, "extmvt", sep = "_"),
     ox_id = paste(ox_id_num, "extmvt", sep = "_"),
  ) %>%
  select(-"C8_International travel controls")
filt_patterns(ox2coronanet_ext_border)
ox2coronanet_ext_border = filter_no_changes(ox2coronanet_ext_border)
ox2coronanet_ext_border = filter_same_description(ox2coronanet_ext_border)


3.10 Public information campaigns

OxCGRT’s ‘H1_Public information campaigns’ collects pretty ‘soft’ policies which CoronaNet doesn’t consider policies. Only the policies with an ordinal value of 2 would be possible to be mapped as Public Awareness Measures.

filter_w_flag("H1_Public information campaigns")
ox2coronanet_info = temp %>%
  mutate(
    unique_id = paste(ox_id, "info", sep = "_"),
     ox_id = paste(ox_id_num, "info", sep = "_"),
    type = case_when(
      `H1_Public information campaigns` == 2 ~ "Public Awareness Measures",
      TRUE ~ as.character(NA)
  )) %>%
  select(-"H1_Public information campaigns")
filt_patterns(ox2coronanet_info)
ox2coronanet_info = filter_no_changes(ox2coronanet_info)
ox2coronanet_info = filter_same_description(ox2coronanet_info)


3.11 Testing policy

OxCGRT’s ‘H2_Testing policy’ are all mapped to CoronaNet’s Health Testing category. They can however be split up into three groups depending on the value and mapped with more detail into type_health_test_who:

  1. ‘only those who both (a) have symptoms AND (b) meet specific criteria (eg key workers, admitted to hospital, came into contact with a known case, returned from overseas)’, which roughly translates to Symptomatic people, Confirmed contact to a person infected with COVID-19.

  2. ‘testing of anyone showing Covid-19 symptoms’ is an exact match for CoronaNet’s Symptomatic people.

  3. ‘open public testing (eg “drive through” testing available to asymptomatic people)’ is an exact match for CoronaNet’s Everyone (i.e. Asymptomatic and symptomatic people)".

filter_wo_flag("H2_Testing policy")
ox2coronanet_test = temp %>%
  mutate(
    type = "Health Testing",
    unique_id = paste(ox_id, "testing", sep = "_"),
     ox_id = paste(ox_id_num, "testing", sep = "_"),
    type_health_test_who = case_when(
      `H2_Testing policy` == 1 ~ "Symptomatic people, Confirmed contact to a person infected with COVID-19",
      `H2_Testing policy` == 2 ~ "Symptomatic people",
      `H2_Testing policy` == 3 ~ "Everyone (i.e. Asymptomatic and symptomatic people)",
      TRUE ~ as.character(NA)
    )
  ) %>%
  select(-"H2_Testing policy")
filt_patterns(ox2coronanet_test )
ox2coronanet_test = filter_no_changes(ox2coronanet_test)
ox2coronanet_test = filter_same_description(ox2coronanet_test)


3.12 Contact tracing

OxCGRT’s ‘H3_Contact tracing’ is a perfect match for CoronaNet’s Health Monitoring type. While it would be possible to make even more fine-grained differentiation, it would not be possible to do this systematically using this automated method.

filter_wo_flag("H3_Contact tracing")
ox2coronanet_tracing = temp %>%
  mutate(
    type = "Health Monitoring",
    unique_id = paste(ox_id, "tracing", sep = "_"),
     ox_id = paste(ox_id_num, "tracing", sep = "_"),
    ) %>%
  select(-"H3_Contact tracing")
filt_patterns(ox2coronanet_tracing )
ox2coronanet_tracing= filter_no_changes(ox2coronanet_tracing)
ox2coronanet_tracing= filter_same_description(ox2coronanet_tracing)


3.13 Emergency investment in healthcare

OxCGRT’s ‘H4_Emergency investment in healthcare’ tracks governemnt spending. A qualitative sample of this data suggests that CoronaNet’s Health Resources type matches well with this indicator.

filter_wo_flag("H4_Emergency investment in healthcare")
ox2coronanet_inv_health = temp %>%
  mutate(
    type = "Health Resources",
    unique_id = paste(ox_id, "inv_health", sep = "_"),
     ox_id = paste(ox_id_num, "inv_health", sep = "_"),
    ) %>%
  select(-"H4_Emergency investment in healthcare")
filt_patterns(ox2coronanet_inv_health )
ox2coronanet_inv_health= filter_no_changes(ox2coronanet_inv_health)
ox2coronanet_inv_health= filter_same_description(ox2coronanet_inv_health)


3.14 Investment in vaccines

OxCGRT’s ‘H5_Investment in Vaccines’ tracks the money spent on vaccine procurement as well as vaccine development spending. This information can be mapped to CoronaNet’s COVID-19 Vaccines category.

filter_wo_flag("H5_Investment in vaccines")
ox2coronanet_inv_vax = temp %>%
  mutate(
    type = "COVID-19 Vaccines",
    unique_id = paste(ox_id, "inv_vax", sep = "_"),
     ox_id = paste(ox_id_num, "inv_vax", sep = "_"),
    ) %>%
  select(-"H5_Investment in vaccines")
filt_patterns(ox2coronanet_inv_vax )
ox2coronanet_inv_vax= filter_no_changes(ox2coronanet_inv_vax)
ox2coronanet_inv_vax= filter_same_description(ox2coronanet_inv_vax)


3.15 Facial Coverings

OxCGRT’s ‘H6_Facial Coverings’ fits in CoronaNet’s Social Distancing category. However, the two datasets have different, incompatabile subcategories which is why this indicator has not been mapped in greater detail.

  • OxCGRT’s H6_Facial Coverings’s ordinal values to CoronaNet’s compliance variable.
    • When H6_Facial Coverings takes on the values of 2,3 or 4, this is equivalent to a ‘Mandatory (Unspecified)’ compliance in the CoronaNet taxonomy
                  filter_w_flag("H6_Facial Coverings")
                  ox2coronanet_mask = temp %>%
                    mutate(
                      compliance = case_when(
                        `H6_Facial Coverings` == 1 ~ "Voluntary/Recommended but No Penalties",
                        `H6_Facial Coverings` %in% c(2,3,4) ~ "Mandatory (Unspecified)",
                        TRUE ~ as.character(NA)
                      ),
                      type = "Social Distancing",
                      unique_id = paste(ox_id, "mask", sep = "_"),
                      ox_id = paste(ox_id_num, "mask", sep = "_"),
                    ) %>%
                    select(-"H6_Facial Coverings")
                  filt_patterns(ox2coronanet_mask)
                  ox2coronanet_mask= filter_no_changes(ox2coronanet_mask)
                  ox2coronanet_mask= filter_same_description(ox2coronanet_mask)


3.16 Vaccination policy

OxCGRT’s ‘H7_Vaccination policy’ is a perfect match for CoronaNet’s COVID-19 Vaccines.

                  filter_w_flag("H7_Vaccination policy")
                  ox2coronanet_vax = temp %>%
                    mutate(
                      type = "COVID-19 Vaccines",
                      unique_id = paste(ox_id, "vax", sep = "_"),
                      ox_id = paste(ox_id_num, "vax", sep = "_")
                    ) %>%
                    select(-"H7_Vaccination policy")
                  filt_patterns(ox2coronanet_vax )
                  ox2coronanet_vax = filter_no_changes(ox2coronanet_vax )
                  ox2coronanet_vax = filter_same_description(ox2coronanet_vax )


3.17 Protection of elderly people

OxCGRT’s ‘H8_Protection of elderly people’ is a perfect match for CoronaNet’s Social Distancing and ‘type_soc_distance’ Restrictions on visiting nursing homes/long term care facilities.

  • OxCGRT’s H8_Protection of elderly people’s ordinal values to CoronaNet’s compliance variable
    • When H8_Protection of elderly people takes on the values of 2,3 or 4, this is equivalent to a ‘Mandatory (Unspecified)’ compliance in the CoronaNet taxonomy.
filter_w_flag("H8_Protection of elderly people")
ox2coronanet_elderly = temp %>%
  mutate(
    compliance = case_when(
      `H8_Protection of elderly people` == 1 ~ "Voluntary/Recommended but No Penalties",
      `H8_Protection of elderly people` %in% c(2,3) ~ "Mandatory (Unspecified)",
      TRUE ~ as.character(NA)
    ),
    type = "Social Distancing",
    unique_id = paste(ox_id, "elderly", sep = "_"),
     ox_id = paste(ox_id_num, "elderly", sep = "_"),
    type_soc_distance = "Restrictions on visiting nursing homes/long term care facilities"
  ) %>%
  select(-"H8_Protection of elderly people")
filt_patterns(ox2coronanet_elderly )
ox2coronanet_elderly = filter_no_changes(ox2coronanet_elderly )
ox2coronanet_elderly = filter_same_description(ox2coronanet_elderly )


4 Map Creation

At the end of this taxonomy mapping exercise, all mapped inidcators are combined together to create the final data frame.

ox_coronanet_map = bind_rows(
  ox2coronanet_elderly,
  ox2coronanet_ext_border,
  ox2coronanet_gatherings,
  ox2coronanet_info,
  ox2coronanet_int_mvt,
  ox2coronanet_mask,
  ox2coronanet_pub_events,
  ox2coronanet_pub_transport,
  ox2coronanet_rest_business,
  ox2coronanet_schools,
  ox2coronanet_stay_home,
  ox2coronanet_test,
  ox2coronanet_tracing,
  ox2coronanet_vax
)

4.1 Cleaning descriptions

A few more cleaning steps to remove observations that are likely incorrectly identified as being policies including:

  • Policies for which there is no link and for which the textual description is less than 50 characters. In such cases, it is difficult to both substantiate what the purported policy is about from the description and impossible to find out more information because of the lack of a link
  • Policies that have ‘Coding review’ in the description (13 policies in total); manual review of these policies suggest that these are not actually policies
  • Policies that reference indicators in the description and have no link (48 in total)
<<<<<<< Updated upstream:RCode/collaboration/oxcgrt/oxcgrt_coronanet_taxonomy.html
# clean up descriptions
ox_coronanet_map  = ox_coronanet_map %>%
  mutate(
    description_nourl =  gsub("See Health ministry's website:|\\[web archive unavailable\\]|See:|Source 1:|Source 2:|See health Ministry's website:|See Ministry of Health website:|scanned major websites such as Zambia National Broadcasting Corporation", "", description_nourl)  ,
    description_nourl = str_trim(description_nourl)
  )
# remove policies with no link and 'no change/no update' etc etc in the description
filt_patterns(ox_coronanet_map )
ox_coronanet_map =  ox_coronanet_map  %>% filter(!(grepl(no_change_patt, description_nourl) & is.na(link)))
# remove policies with no link and very short description (check of sample of these policies suggests they are virtually all 'no change' policies)
ox_coronanet_map = ox_coronanet_map %>% filter(!(is.na(link) & nchar(description_nourl)<50))
# remove policies with coding review in the description; very few of them (13 as of September 10, 2021) but seem confusing/not helpful
ox_coronanet_map  = ox_coronanet_map %>% filter(!grepl("Coding review", description))
# removing policies which reference indicators in the description and have no link; very few of them (48 as of September 10, 2021); overall confusing/not helfpul
ox_coronanet_map = ox_coronanet_map %>% filter(!(is.na(link) & grepl("C1|C2|C3|C4|C5|C6|C7|C8|H1|H2|H3|H4|H5|H6|H7|H8", description)))  
# remove irrelevant policies once more: 
filt_patterns(ox_coronanet_map)
ox_coronanet_map = filter_no_changes(ox_coronanet_map)
ox_coronanet_map = ox_coronanet_map %>%
  mutate(
    description_nourl = ifelse(description_nourl=="", description, description_nourl)
  )
data.table:::fwrite(ox_coronanet_map,  here("data", "collaboration", "oxcgrt", "ox_coronanet_map.csv.gz"))
saveRDS(ox_coronanet_map, (here("data", "collaboration", "oxcgrt", "ox_coronanet_map.rds")))
=======
amp_coronanet_map = data.frame(unique_id = covidamp$unique_id,
                               entry_type = NA,
                               correct_type= NA,
                               update_type= NA,
                               update_level= NA,
                               description= covidamp$Policy_description,
                               date_announced= as.Date(covidamp$Issued_date),
                               date_start= as.Date(covidamp$Effective_start_date),
                               date_end= NA, 
                               country = covidamp$Authorizing_country_name,
                               ISO_A3 = covidamp$Authorizing_country_ISO,
                               ISO_A2 = NA,
                               init_country_level = NA,
                               domestic_policy = NA,
                               target_init_same = NA,
                               province = covidamp$Authorizing_state_province_if_applicable,
                               city=NA,
                               init_other = covidamp$Authorizing_local_area,
                               type= NA,
                               type_sub_cat= NA,
                               type_text= NA,
                               institution_status= NA,
                               target_country= covidamp$Affected_country_name,
                               target_geog_level= NA,
                               target_region= NA,
                               target_province= covidamp$Affected_state_province,
                               target_city= covidamp$Affected_local_area,
                               target_other= NA,
                               target_who_what= NA,
                               target_who_gen = NA,
                               target_direction= NA,
                               travel_mechanism= NA,
                               institution_cat = NA,
                               compliance= NA,
                               enforcer= NA,
                               link = ifelse(!is.na(covidamp$Data_source_for_policy_announcement),covidamp$Data_source_for_policy_announcement,
                                             ifelse(!is.na(covidamp$Data_source_for_law_policy), covidamp$Data_source_for_law_policy,
                                            covidamp$Policy_law_name)),
                               pdf_link = ifelse(!is.na(covidamp$Attachment_for_policy),covidamp$Attachment_for_policy,
                                                 ifelse(!is.na(covidamp$PDF_file_name_of_law_policy), covidamp$PDF_file_name_of_law_policy, NA)),

                               date_updated = NA)


2.1 Add Model-Based Predictions

This code adds in model-based predictions for the ‘type’ of policy an observation is provided in the who_predicts.csv file. This data was provided by the Coronanet Data Science Team. The models used to create those predictions were trained on the Coronanet data, those predictions might therefore not be accurate and are to be treated as suggestive. ‘type_alt’ refers to the more confident guess by the models and ‘type_alt_alt’ contains the second best predictions from these predictive models.

amp_coronanet_map = amp_coronanet_map %>%  
  left_join(amp_predicts %>% 
  dplyr::select(unique_id = `Unique ID` , 
                type_alt = predict_1,
                type_alt_2 = predict_2))  


2.2 Countries

The following code adjust for the different ways each tracker documents policies originating from certain regions of the world. In particular:

  • COVIDAMP categorizes England, Northern Ireland, Scotland and Wales as separate countries. The CoronaNet taxonomy considers these regions as provinces within the United Kingdom and the following code adjusts this data accordingly.

  • COVIDAMP categorizes tribal nations in the United States as separate countries. The CoronaNet taxonomy considers these regions as local governmental levels within the United States and the following code adjusts this data accordingly.

amp_coronanet_map = amp_coronanet_map %>% 
  mutate(
      province = case_when(
      is.na(country) & country == "England (GB-ENG)" ~ "England",
      is.na(country) & country ==  "Northern Ireland (GB-NIR)" ~ "Northern Ireland",
      is.na(country) & country ==  "Scotland (GB-SCT)" ~ "Scotland", 
      is.na(country) & country == "Wales (GB-WLS)" ~ "Wales" ,
      grepl("Tribe|Sac and Fox Nation|Yavapai Nation|Blackfeet Nation|Navajo|Crow Nation|Community|Colony|Reservation|Potawatomi Nation|Tohono O'odham|Luik", province) ~ as.character(NA),
      TRUE ~ province),
    init_other = case_when(
grepl("Tribe|Sac and Fox Nation|Yavapai Nation|Blackfeet Nation|Navajo|Crow Nation|Community|Colony|Reservation|Potawatomi Nation|Tohono O'odham|Luik", country) ~ country,
      TRUE~init_other),
    country = case_when(
      is.na(country) & country == "England (GB-ENG)" ~ "United Kingdom" ,
      is.na(country) & country ==  "Northern Ireland (GB-NIR)" ~ "United Kingdom",
      is.na(country) & country ==  "Scotland (GB-SCT)" ~ "United Kingdom",
      is.na(country) & country == "Wales (GB-WLS)"  ~ "United Kingdom",
      grepl("Tribe|Sac and Fox Nation|Yavapai Nation|Blackfeet Nation|Navajo|Crow Nation|Community|Colony|Reservation|Potawatomi Nation|Tohono O'odham|Luik", country) ~ "United States of America",
      TRUE~ country),
    ISO_A3 = 
      case_when(
        ISO_A3 %in% c('GB-SCT', "GB-ENG", 'GB-WLS', "GB-NIR")~ "GBR",
        grepl("Tribe|Sac and Fox Nation|Yavapai Nation|Blackfeet Nation|Navajo|Crow Nation|Community|Colony|Reservation|Potawatomi Nation|Tohono O'odham|Luik", init_other) ~ "USA",
        TRUE ~ ISO_A3
      ),
    
  )


2.3 Cities and Counties

The COVIDAMP variable Authorizing_local_area does not make distinctions between cities and counties whereas the CoronaNet taxonomy does. To the extent possible, the following code separates out cities and counties through the use of regular expressions into the city and init_other variables in the CoronaNet taxonomy accordingly.

init <- covidamp %>%
  mutate(
    init_other  = case_when(
         grepl("County|county", Authorizing_local_area) ~ Authorizing_local_area,
         TRUE ~ as.character(NA)
    ),
    city = case_when(
      grepl("Luik", Authorizing_local_area) ~ Authorizing_local_area,
      grepl("city|City", Authorizing_local_area) ~ Authorizing_local_area,
      is.na(init_other) ~  Authorizing_local_area,
      TRUE ~ as.character(NA)
    )
  ) %>% select(
    unique_id, init_other, city
  )
amp_coronanet_map = rows_patch(amp_coronanet_map, init, "unique_id")


2.4 End dates

COVIDAMP captures information on end dates in two separate variables, the anticipated end date and actual end date. The closest match for these variables in the CoronaNet taxonomy is its date_end (Note, additionally the CoronaNet taxonomy also captures qualitative information about end dates in its date_end_spec variable but this is not a close conceptual match ot the COVIDAMP variables). In order to retain as much information as possible from COVIDAMP about the end dates, the following information is mapped into the CoronaNet date_end variable.

  • If te anticipated end date is the same as the actual end date and neither of them is NA, the actual end date is used.
  • If the anticipated end date is different than the actual end date and neither of them is NA, both of the end dates are used.
  • If there is only an actual end date captured and no anticipated end date, the actual end date is used.
  • If there is only an anticipated end date captured and no actual end date, the anticipated end date is used.
  • If there is no information recorded in either anticipated end date and actual end date, then no end date is recorded.
end_date =
  covidamp %>%
  mutate(
    date_end =
      case_when(
        !is.na(Actual_end_date) & !is.na(Anticipated_end_date) & Actual_end_date == Anticipated_end_date ~  Actual_end_date,
        !is.na(Actual_end_date) & !is.na(Anticipated_end_date) & Actual_end_date != Anticipated_end_date ~  paste0("Actual end date:",  Actual_end_date, ' ; anticipated end date: ', Anticipated_end_date),
        !is.na(Actual_end_date) & is.na(Anticipated_end_date)  ~   Actual_end_date,
        is.na(Actual_end_date) & !is.na(Anticipated_end_date)  ~   Anticipated_end_date,
        !is.na(Actual_end_date) & !is.na(Anticipated_end_date) ~ as.character(NA)
      )
  ) %>% select(unique_id, date_end)
amp_coronanet_map = rows_patch(amp_coronanet_map,end_date, "unique_id")


2.5 Policy Level

COVIDAMP captures information on the level of government that authorizes a given policy action in its Authorizing_level_of_government variable, which is a direct conceptual match for CoronaNet’s init_country_level variable. The values for this field however need to be adjusted slightly to match the CoronaNet taxonomy:

  • Policies originating from England, Northern Ireland, Scotland and Wales are changed from policies that originate at the Country level in the COVIDAMP taxonomy to the Provincial level in the CoronaNet taxonomy, since CoronaNet considers these regions as provinces of Great Britain rather than as separate countries as COVIDAMP does.
  • Policies coded as taking the value of Country in the COVIDAMP taxonomy are renamed as National to match the CoronaNet taxonomy
  • Policies coded as taking the value of State/Province in the COVIDAMP taxonomy are renamed as Provincial to match the CoronaNet taxonomy
  • Policies coded as taking the value of Tribal nation in the COVIDAMP taxonomy are kept as is although there is no corresponding category in the CoronaNet taxonomy. These policies will be processed later during the harmonisation process.
  • Policies coded as taking the value of Local in the COVIDAMP taxonomy are alternatively coded as taking the value of Other (e.g., county) or Municipal depending on whether the kewords of country or city are present in the localities name.

In addition, the CoronaNet taxonommy also documents whether the government which initiates a policy is the same as the geographic target of the policy in its target_init_same variable. We extract this information from the COVIDAMP data as follows:

  • target_init_same (i.e. whether the geographical target of the policy matches the geographical location the authorizing governemnt body sits in) takes the value of Yes if the Authorizing_country_name is the same as the Affected_country_name and No otherwise.
pol_level = covidamp %>%
  select(unique_id, Authorizing_level_of_government, Authorizing_country_ISO,Authorizing_country_name, Affected_country_ISO, Authorizing_local_area) %>%
  mutate(init_country_level = case_when(
  Authorizing_country_name  %in% c( "England (GB-ENG)", 
                         "Northern Ireland (GB-NIR)",
                         "Scotland (GB-SCT)",
                         "Wales (GB-WLS)") ~ "Provincial",
    # grepl("Tribe|Sac and Fox Nation|Yavapai Nation|Blackfeet Nation|Navajo|Crow Nation|Community|Colony|Reservation|Potawatomi Nation|Tohono O'odham|Luik", Authorizing_country_name)~ "Other (e.g., county)",
    Authorizing_level_of_government == "Country" ~ "National",
    Authorizing_level_of_government == "State / Province" ~ "Provincial",
    Authorizing_level_of_government == "Tribal nation" ~ "Tribal nation",
    Authorizing_level_of_government == "Local"  &    grepl("County|county", Authorizing_local_area) ~ "Other (e.g., county)",
    Authorizing_level_of_government == "Local"  &    grepl("city|City", Authorizing_local_area) ~ "Municipal",
       Authorizing_level_of_government == "Local"  &    !grepl("city|City|County|county", Authorizing_local_area) ~ "Other (e.g., county)",
  )) %>%
  mutate(target_init_same = case_when(
    Authorizing_country_name == Affected_country_name ~ "Yes",
    TRUE ~ "No"
  )) %>%
  select(unique_id, init_country_level)
amp_coronanet_map = rows_patch(amp_coronanet_map, pol_level, "unique_id")


2.6 Target Regions

The CoronaNet taxonommy also documents what level of government a policy targets in its target_geog_level variable. We extract this information from the COVIDAMP data as follows:

  • If a policy does not recorded a state or province or local area that it specifically targets, target_geog_level takes on the value of One or more countries, but not all countries
  • If a policy records state or province that it specifically targets but no local area that it specifically targets, target_geog_level takes on the value of One or more provinces within a country
  • If a policy records a local area that it specifically targets, target_geog_level takes on the value of One or more cities within a country
target_reg = covidamp %>%
  select(unique_id, Affected_country_name, Affected_state_province, Affected_local_area) %>%
  mutate(target_geog_level = case_when(
    is.na(Affected_state_province) & is.na(Affected_local_area) ~ "One or more countries, but not all countries",
    is.na(Affected_local_area) ~ "One or more provinces within a country",
    !is.na(Affected_local_area) ~ "One or more cities within a country"
  )) %>%
  select(-c(2,3,4))
  
amp_coronanet_map = rows_patch(amp_coronanet_map, target_reg, "unique_id")


2.7 Policy update level

  • The COVIDAMP Policy_relaxing_or_restricting, which records whether a policy is relaxing or strenthening over tie, is nearly direct conceptual match for CoronaNet’s update_level. Both CoronaNet and COVIDAMP refer to policies that ease over time as Relaxing. COVIDAMP refers to policies that become more restrictive over time as Restricting while CoronaNet refers to such policies as Strenthening.

  • However, COVIDAMP’s value 9of Other for the variable cannot be directly mapped to the CoronaNet taxonomy; such mappings with be done downstream during manual harmonisation. For the purposes of this mapping, these are recoded as NA.

amp_coronanet_map$update_level = covidamp$Policy_relaxing_or_restricting
amp_coronanet_map$update_level = na_if(amp_coronanet_map$update_level, "Other")

2.8 Target Who/ What

The COVIDAMP taxonomy captures information as to the demographics of a policy in its Policy_subtargets, which is a direct conceptual map to the target_who_gen variable in the CoronaNet taxonomy. Not all values within this variable are directly mappable however. The following code maps as many values as are directly mappable as possible and leaves the rest for manual harmonisation to resolve downstream.

temp = covidamp %>% 
  select(unique_id, Policy_subtarget) %>%
  mutate(target_who_gen = case_when(
    grepl("Nursing homes/assisted living facility", Policy_subtarget) ~ "People in nursing homes/long term care facilities",
    grepl("Homeless shelters/homeless individuals", Policy_subtarget) ~ "Homeless population",
    grepl("Non essential workers (inclusive)", Policy_subtarget) ~ "Non-essential workers (please note their occupation in the text entry where applicable)",
    grepl("Essential workers (inclusive)",Policy_subtarget) ~ "Essential workers (please note their occuption in the text entry where applicable)",
    grepl("Migrant workers/Refugees/asylum seekers", Policy_subtarget) ~ "Migrant workers (please note their occupation in the text entry where applicable)",
  ),
  target_who_what = case_when(grepl("Travelers", Policy_subtarget) ~ "All Travelers (Citizen Travelers + Foreign Travelers)"
    )) %>%
  select(-c(2))
amp_coronanet_map = rows_patch(amp_coronanet_map, temp, "unique_id")


2.9 Categories Cleaning

The following code fixes some issues with the policy categories and subcategories in the COVIDAMP dataset. In particular, it appears that some of the COVIDAMP policy subcategories are not mapped to the correct policy category. We fix these issues in the below in order to make the subsequent mapping of the COVIDAMP taxonomy into the CoronaNet taxonomy as error-free as possible.

temp = covidamp %>%
  select(unique_id, Policy_category, Policy_subcategory) %>%
  mutate(type = case_when(
    grepl("Domestic travel restriction|International travel restriction", Policy_subcategory) ~ "Travel restrictions",
    grepl("General emergency declaration|Public health emergency declaration", Policy_subcategory) ~ "Emergency declarations",
    grepl("Other labor protections|Support for essential workers|Budget modifications|Relief funding|Anti-price gouging measures|Tax delay",Policy_subcategory) ~ "Enabling and relief measures",
    grepl("Other measures to support public health and clinical capacity|Risk Communication|Other measures to support public health and clinical capacity|Coverage for cost of testing|Elective procedure delay or cancellation", Policy_subcategory) ~ "Support for public health and clinical capacity",
    grepl("Authorization", Policy_subcategory) ~ "Authorization and enforcement",
    grepl("Testing|Contact tracing", Policy_subcategory) ~ "Contact tracing/Testing",
    grepl("Health screening|Adaptation and mitigation measures|Distancing mandate|Mass gathering restrictions|Quarantine|School closures|Quarantine|Curfews|Lockdown|Event delays or cancellations|Public service closures|Isolation|Stay at home|Private sector closures|Alternative election measures|Other forms of social distancing", Policy_subcategory) ~ "Social distancing",
    grepl("Face mask", Policy_subcategory) ~ "Face mask",
    TRUE ~ Policy_category
  )) %>%
  select(-c(2,3)) %>%
  rename(Policy_category = type)

covidamp = rows_update(covidamp, temp, "unique_id")


3 Policy Type

3.1 Social Distancing

The following code maps how COVIDAMP captures social distancing policies to the CoronaNet taxonomy. While when there is no one to one matching of the Social distancing Policy_category to the CoronaNet taxonomy, it is possible to use the Policy_subcategory to create one to one matchings for the type variable in the CoronaNet taxonomy. In particular, the following code matches the following for policies that take on the value of Social distancing in the Policy_category variable::

  • Observations that take on the value of Other forms of social distancing, Visitor restrictions, Distancing mandate, Face covering or takes on no value in Policy_subcategory variable can be mapped as Social Distancing for the type variable in the CoronaNet taxonomy.

  • Observations that take on the value of Lockdown, Stay at home, Safer at home or Isolation in the Policy_subcategory variable can be mapped as Lockdown for the type variable in the CoronaNet taxonomy.

  • Observations that take on the value of Alternative election measures, Public service closures or Election delays in the Policy_subcategory variable can be mapped as Restriction and Regulation of Government Services for the type variable in the CoronaNet taxonomy.

  • Observations that take on the value of Private sector closures or Adaptation and mitigation measures in the Policy_subcategory variable can be mapped as Restriction and Regulation of Businesses for the type variable in the CoronaNet taxonomy.

  • Observations that take on the value of Mass gathering restrictions, Event delays or cancellations, or Prison population reduction in the Policy_subcategory variable can be mapped as Restrictions of Mass Gatherings for the type variable in the CoronaNet taxonomy.

  • Observations that take on the value of School closures in the Policy_subcategory variable can be mapped as Closure and Regulation of Schools for the type variable in the CoronaNet taxonomy.

  • Observations that take on the value of Quarantine in the Policy_subcategory variable can be mapped as Quarantine for the type variable in the CoronaNet taxonomy.

  • Observations that take on the value of Curfews in the Policy_subcategory variable can be mapped as Curfew for the type variable in the CoronaNet taxonomy.

  • Observations that take on the value of Health screening in the Policy_subcategory variable can be mapped as Health Monitoring for the type variable in the CoronaNet taxonomy.

social_distancing = covidamp %>%
  filter(Policy_category == "Social distancing") %>%
  select(unique_id, Policy_category, Policy_subcategory) %>%
  mutate(type = case_when(
  
  Policy_subcategory %in% c(
    "Other forms of social distancing",
    "Visitor restrictions",
    "Distancing mandate" ,
    "Face covering"
    ) ~ "Social Distancing",
  
  Policy_subcategory %in% c( 
      "Lockdown",
      "Stay at home",
      "Safer at home",
      "Isolation") ~ "Lockdown",
  
  Policy_subcategory %in% c( 
    "Alternative election measures",
    "Public service closures",
    "Election delays"
    ) ~ "Restriction and Regulation of Government Services",
  
  Policy_subcategory %in% c(
    "Private sector closures",
    "Adaptation and mitigation measures"
    )~ "Restriction and Regulation of Businesses",
  
  
  Policy_subcategory %in% c( 
    "Mass gathering restrictions",
    "Event delays or cancellations",
    "Prison population reduction")~ "Restrictions of Mass Gatherings",
  
    
  Policy_subcategory == "School closures" ~ "Closure and Regulation of Schools",
  Policy_subcategory == "Quarantine" ~ "Quarantine",
  Policy_subcategory == "Curfews" ~ "Curfew",
  Policy_subcategory == "Health screening" ~ "Health Monitoring",
  
  
  is.na(Policy_subcategory) ~ "Social Distancing",
  
  
  
  TRUE ~ as.character(NA)
  ))%>%
  select(-c(2,3))

amp_coronanet_map = rows_patch(amp_coronanet_map, social_distancing, "unique_id")


3.2 Contact tracing/Testing

The following code maps how COVIDAMP captures contact tracing and testing policies to the CoronaNet taxonomy. Though there is no one to one matching of the Contact tracing/Testing Policy_category to the CoronaNet taxonomy, it is possible to use the Policy_subcategory to create one to one matchings for the type variable in the CoronaNet taxonomy. In particular, the following code matches the following for policies that take on the value of Contact tracing/Testing in the Policy_category variable:

  • Observations that take on the value of Testing or no vaolue Policy_subcategory variable can be mapped as Health Testing for the type variable in the CoronaNet taxonomy.

  • Observations that take on the value of Contact tracing Policy_subcategory variable can be mapped as Health Monitoring for the type variable in the CoronaNet taxonomy. A more detailed mapping of to policy subtypes in the CoronaNet taxonomy would theoretically be possible but would not be possible to do easily. As such it was not done in this initial mapping but rather reserved for downstream manual data harmonization.

contacts = covidamp %>%
  filter(Policy_category == "Contact tracing/Testing") %>%
  select(unique_id, Policy_category, Policy_subcategory) %>%
  mutate(type = case_when(
    Policy_subcategory == "Testing" ~ "Health Testing",
    Policy_subcategory == "Contact tracing" ~ "Health Monitoring",
    is.na(Policy_subcategory) ~ "Health Testing",
     TRUE ~ as.character(NA)
  ))%>%
  select(-c(2,3))
amp_coronanet_map = rows_patch(amp_coronanet_map, contacts, "unique_id")


3.3 Support for public health and clinical capacity

The following code maps how COVIDAMP captures support for public health and clinical capacity to the CoronaNet taxonomy.

  • The COVIDAMP taxonomy aims to capture such policies by coding the Policy_category as Support for public health and clinical capacity

  • The CoronaNet taxonomy aims to capture such policies by coding the type variable as Health Resources

  • Note while it may have been possible to addtionally map policy sub types within this larger policy type, such mappings would have been imprecise and we reserved them for downstream manual data harmoization.

support_health = covidamp %>%
  filter(Policy_category == "Support for public health and clinical capacity") %>%
  select(unique_id, Policy_category, Policy_subcategory) %>%
  mutate(type =  "Health Resources")%>%
  select(-c(2,3))
amp_coronanet_map = rows_patch(amp_coronanet_map, support_health, "unique_id")


3.4 Enabling and relief measures

The following code maps how COVIDAMP captures relief measure policies to the CoronaNet taxonomy. Though there is no one to one matching of the Enabling and relief measures Policy_category to the CoronaNet taxonomy, it is possible to use the Policy_subcategory to create one to one matchings for the type variable in the CoronaNet taxonomy. In particular, the following code matches the following for policies that take on the value of Enabling and relief measures in the Policy_category variable:

  • Observations that take on the value of Regulatory relief, Other relief measures, Relief funding , Eviction and foreclosure delays, Budget modifications, Modification of unemployment benefits, Leave entitlement adjustments, Other labor protections, Anti-price gouging measures, Utility payment delay, Utility payment, Stimulus payments, Mortgage payment support, Hazard pay", or takes on no value in Policy_subcategory variable can be mapped as Other Policy Not Listed Above (econ) for the type variable in the CoronaNet taxonomy.

  • Observations that take on the value of Extension of public services, Tax delay, Remote Notarization in the Policy_subcategory variable can be mapped as Restriction and Regulation of Government Services for the type variable in the CoronaNet taxonomy.

  • Observations that take on the value of Support for essential workers in the Policy_subcategory variable can be mapped as Health Resources for the type variable in the CoronaNet taxonomy.

  • Observations that take on the value of Early prison release in the Policy_subcategory variable can be mapped as Restrictions of Mass Gatherings for the type variable in the CoronaNet taxonomy.

relief_measures = covidamp %>%
  filter(Policy_category == "Enabling and relief measures") %>%
  select(unique_id, Policy_category, Policy_subcategory) %>%
  mutate(type = case_when(
    Policy_subcategory %in% c(
      "Regulatory relief",
      "Other relief measures",
      "Relief funding" ,
      "Eviction and foreclosure delays",
      "Budget modifications",
      "Modification of unemployment benefits" ,
      "Leave entitlement adjustments",
      "Other labor protections" ,
      "Anti-price gouging measures",
      "Utility payment delay",
      "Utility payment",
      "Stimulus payments",
      "Mortgage payment support",
      "Hazard pay")~ "Other Policy Not Listed Above (econ)",
    
    Policy_subcategory %in% c(
      "Extension of public services",
      "Tax delay",
      "Remote Notarization"
    ) ~ "Restriction and Regulation of Government Services",
  
    Policy_subcategory == "Support for essential workers" ~ "Health Resources",
    Policy_subcategory == "Early prison release" ~ "Restrictions of Mass Gatherings",

    is.na(Policy_subcategory) ~ "Other Policy Not Listed Above (econ)",
    
    TRUE ~ as.character(NA)
  ))%>%
  select(-c(2,3))

amp_coronanet_map = rows_patch(amp_coronanet_map, relief_measures, "unique_id")


3.5 Travel restrictions

The following code maps how COVIDAMP captures travel restriction policies to the CoronaNet taxonomy. Though there is no one to one matching of the Travel restrictions Policy_category to the CoronaNet taxonomy, it is possible to use the Policy_subcategory to create one to one matchings for the type variable in the CoronaNet taxonomy. In particular, the following code matches the following for policies that take on the value of Travel restrictions in the Policy_category variable:

  • Observations that take on the value of International travel restriction, Domestic travel restrictions (interstate) or take on no value in the Policy_subcategory variable can be mapped as External Border Restrictions for the type variable in the CoronaNet taxonomy.

  • Observations that take on the value of Domestic travel restriction or Domestic travel restrictions (intrastate) in the Policy_subcategory variable can be mapped as Internal Border Restrictions for the type variable in the CoronaNet taxonomy.

travel_restrictions = covidamp %>%
  filter(Policy_category == "Travel restrictions") %>%
  select(unique_id, Policy_category, Policy_subcategory) %>%
  mutate(type = case_when(
    Policy_subcategory %in% c(
      "International travel restriction",
       "Domestic travel restrictions (interstate)") ~ "External Border Restrictions",
    Policy_subcategory %in% c(
      "Domestic travel restriction",
      "Domestic travel restrictions (intrastate)")~ "Internal Border Restrictions",

    is.na(Policy_subcategory) ~ "External Border Restrictions",
  TRUE ~ as.character(NA)
  ))%>%
  select(-c(2,3))
amp_coronanet_map = rows_patch(amp_coronanet_map, travel_restrictions, "unique_id")


3.6 Emergency declarations

The following code maps how COVIDAMP captures declarations of emergency to the CoronaNet taxonomy.

  • The COVIDAMP taxonomy aims to capture such policies by coding the Policy_category as Emergency declarations

  • The CoronaNet taxonomy aims to capture such policies by coding the type variable as Declaration of Emergency

emergency = covidamp %>%
  filter(Policy_category == "Emergency declarations") %>%
  select(unique_id, Policy_category, Policy_subcategory) %>%
  mutate(type = "Declaration of Emergency"
  )%>%
  select(-c(2,3))
amp_coronanet_map = rows_patch(amp_coronanet_map, emergency, "unique_id")


3.7 Military mobilization

The following code maps how COVIDAMP captures military mobilization to the CoronaNet taxonomy.

  • The COVIDAMP taxonomy aims to capture such policies by coding the Policy_category as *Military mobilization**

  • The CoronaNet taxonomy does not systematically capture policies about military mobilization. As such, these policies have been mapped such that thetype variable takes the value of Other Policy Not Listed Above

CoronaNet does not capture policies about military mobilization, therefore it has been mapped to ‘Other Policy Not Listed Above’.

military = covidamp %>%
  filter(Policy_category == "Military mobilization") %>%
  select(unique_id, Policy_category, Policy_subcategory) %>%
  mutate(type = "Other Policy Not Listed Above"
  ) %>%
  select(-c(2,3))
amp_coronanet_map = rows_patch(amp_coronanet_map, military, "unique_id")


3.8 Authorization and Enforcement

The following code maps how COVIDAMP captures policies focused on giving various (non-) governmental bodies more authorization and how the enforcment of policies is handled to the CoronaNet taxonomy despite the fact that it cannot be directly done. Note that while CoronaNet captures how policies are enforced, but does not capture changes in the enforcement as stand-alone policies but rather in its compliance variable.

  • On manual inspection of the policies coded with the value of Authorization and enforcement for the variable Policy_category and Enforcement for the variable Policy_subcategory, we found that they could be mapped as either New Task Force, Bureau or Administrative Configuration, Restriction and Regulation of Businesses, Restrictions of Mass Gatherings, Restriction and Regulation of Government Services, Social Distancing, Curfew, Quarantine,Lockdown, Health Testing, External Border Restrictions, Internal Border Restrictions or Other Policy Not Listed Above

  • Based on keywords in the textual description of these policies, which we identified based on manual inspection of the data, we customized the code to sort these policies into different values in CoronaNet’s type variable, with Other Policy Not Listed Above being the default option when no other keyword was found. While this does not provide a perfect mapping of these policies, it is sufficient for a large proportion of the data; downstream manual harmonization will correct for any mis-mappings

authorization = covidamp %>%
  filter(Policy_category == "Authorization and enforcement") %>%
  select(unique_id, Policy_category, Policy_subcategory, Policy_description) %>%
  mutate(type = case_when(
    Policy_subcategory == "Authorization" ~ "New Task Force, Bureau or Administrative Configuration",
    
    Policy_subcategory == "Enforcement"  & grepl("fitness|bars|kiosk|Business|alcohol|workplace|employ|worker|food|store|business|sport|Bank|bank|Personal care servi|Floral|estaurant", Policy_description) ~ "Restriction and Regulation of Businesses",
    Policy_subcategory == "Enforcement"  & 
      grepl("density|together in a public|together in public|gathering", Policy_description) ~ "Restrictions of Mass Gatherings",
    Policy_subcategory == "Enforcement"  & 
      grepl("public seating|campground|license", Policy_description) ~ "Restriction and Regulation of Government Services" ,
    Policy_subcategory == "Enforcement"  & 
      grepl("education|school", Policy_description) ~ "Restriction and Regulation of Government Services" ,
    Policy_subcategory == "Enforcement"  & 
      grepl("physical distanc|face cover|nursing|6ft|mask|meter|social distancing", Policy_description) ~ "Social Distancing" ,
    Policy_subcategory == "Enforcement"  & grepl("urfew", Policy_description) ~ "Curfew" ,
    Policy_subcategory == "Enforcement"  & grepl("quarantine", Policy_description) ~ "Quarantine" ,
    Policy_subcategory == "Enforcement"  & grepl("isolation", Policy_description) ~ "Lockdown or Quarantine" ,
    Policy_subcategory == "Enforcement"  & grepl("stay at home|lockdown|Lockdown", Policy_description) ~ "Lockdown" ,
    Policy_subcategory == "Enforcement"  & grepl("test", Policy_description) ~ "Health Testing" ,
    Policy_subcategory == "Enforcement"  & grepl("travel|border closure", Policy_description) ~ "External Border Restrictions" ,
    Policy_subcategory == "Enforcement"  & grepl("Incorporates provinces of Alberta and Saskatchewan", Policy_description) ~ "New Task Force, Bureau or Administrative Configuration" ,
    Policy_subcategory == "Enforcement"  & grepl("road closure", Policy_description) ~ "Internal Border Restriction" ,
    Policy_subcategory == "Enforcement" ~ "Other Policy Not Listed Above",
    Policy_subcategory == "Courts" ~ "Other Policy Not Listed Above",
    is.na(Policy_subcategory) ~ "Other Policy Not Listed Above",
    TRUE ~ as.character(NA)
  ))%>%
  select(unique_id, type)
amp_coronanet_map = rows_patch(amp_coronanet_map, authorization, "unique_id")


3.9 Face mask

The following code maps how COVIDAMP captures face mask policies to the CoronaNet taxonomy.

  • The COVIDAMP taxonomy aims to capture such policies by coding the Policy_category as Face mask

  • The CoronaNet taxonomy aims to capture such policies by coding the type variable as Social Distancing. A more detailed mapping of to policy subtypes in the CoronaNet taxonomy would theoretically be possible but would not be possible to do easily. As such, it was not done in this initial mapping but rather reserved for downstream manual data harmonization.

mask = covidamp %>%
  filter(Policy_category == "Face mask") %>%
  select(unique_id, Policy_category, Policy_subcategory) %>%
  mutate(type =  "Social Distancing"
  )%>%
  select(-c(2,3))
amp_coronanet_map = rows_patch(amp_coronanet_map, mask, "unique_id")


3.10 Vaccine

The following code maps how COVIDAMP captures vaccination policies to the CoronaNet taxonomy.

  • The COVIDAMP taxonomy aims to capture such policies by coding the Policy_category as Vaccinations

  • The CoronaNet taxonomy aims to capture such policies by coding the type variable as COVID-19 Vaccine. In a section below, we further map sub types for COVID-19 vaccinations.

vaccine = covidamp %>%
  filter(Policy_category == "Vaccinations") %>%
  select(unique_id, Policy_category, Policy_subcategory) %>%
  mutate(type = "COVID-19 Vaccines"
  )%>%
  select(-c(2,3))
amp_coronanet_map = rows_patch(amp_coronanet_map, vaccine, "unique_id")


4 Policy Subtypes

In the following section, we further map the policy subtypes documented in the COVIDAMP variable Policy_subtarget to the corresponding CoronaNet variable type_sub_cat for a subset of the dataset.

4.1 Business Restrictions

The following code maps how COVIDAMP captures policies regarding business restrictions to the CoronaNet taxonomy despite the fact that it cannot be directly done.

  • The following code extracts keywords from the Policy_subtarget variable in the COVIDAMP taxonomy to determine whether as a business should be mapped as a Non-essential business or an Essential business in the business_cat variable. These keywords were chosen based on a manual inspection of the COVIDAMP data.

  • The following code extracts keywords from the Policy_subtarget variable in the COVIDAMP taxonomy to determine what type of business is being targeted into the type_sub_cat variable. These keywords were chosen based on a manual inspection of the COVIDAMP data.

temp = amp_coronanet_map %>%
  filter(type == "Restriction and Regulation of Businesses") %>%
  select(unique_id)

temp = covidamp[covidamp$unique_id %in% temp$unique_id,]
business_cat = temp %>%
  select(unique_id, Policy_subtarget) %>%
  mutate(
    non_essential_dum = ifelse(grepl("Non essential business", Policy_subtarget, ignore.case = F),
                               "Non-Essential Businesses", 
                               NA ),
    essential_dum = ifelse(grepl("Essential business", Policy_subtarget, ignore.case = F),
                           "Essential Businesses", NA )) %>%
  unite(institution_cat, 
        essential_dum, 
        non_essential_dum, na.rm = TRUE, sep = ',' ) %>%
  select(-c(2))
amp_coronanet_map = rows_patch(amp_coronanet_map, business_cat, "unique_id")


business_type = temp %>%
  select(unique_id, Policy_subtarget) %>%
  mutate(
    grocery_dum = ifelse(grepl("Grocery store", Policy_subtarget, ignore.case = F), "Supermarkets/grocery stores", NA ),
    hotel_dum = ifelse(grepl("Hotels/lodging", Policy_subtarget, ignore.case = F), "Paid lodgings (e.g. hotels)", NA ),
    personal_dum = ifelse(grepl("Personal care facilities", Policy_subtarget, ignore.case = F), "Personal Grooming Businesses (e.g. hair salons)", NA ),
    pharmacy_dum = ifelse(grepl("Pharmacy", Policy_subtarget, ignore.case = F), "Pharmacies", NA ),
    rest_dum = ifelse(grepl("Restaurants/bars", Policy_subtarget, ignore.case = F), "Restaurants,Bars", NA ),
    retail_dum = ifelse(grepl("Retail stores (not including food)", Policy_subtarget, ignore.case = F), "Retail Businesses", NA ),
    farm_dum  = ifelse(grepl("Farming/Agriculture/Food processing", Policy_subtarget, ignore.case = F), "Agriculture, forestry and fishing", NA)) %>%
  unite(type_sub_cat, grocery_dum, hotel_dum, personal_dum, pharmacy_dum, rest_dum, retail_dum, farm_dum, na.rm = TRUE, sep = ',' ) %>%
  select(-c(2))

amp_coronanet_map = rows_patch(amp_coronanet_map, business_type, "unique_id")


4.2 Schools

The following code maps how COVIDAMP captures school closures/ restrictions to the CoronaNet taxonomy.

  • COVIDAMP and CoronaNet document whether a policy is targeted toward preschools, primary schools, secondary schools and higher eduction institutions but they use slightly different language to do so. The following extracts this information from the Policy_subtarget variable in the COVIDAMP taxonomy to determine what school type is being targeted into the type_sub_cat variable. These keywords were chosen based on a manual inspection of the COVIDAMP data.
temp = amp_coronanet_map %>%
  filter(type == "Closure and Regulation of Schools") %>%
  select(unique_id)
temp = covidamp[covidamp$unique_id %in% temp$unique_id,]
school_type = temp %>%
  select(unique_id, Policy_subtarget) %>%
  mutate(
    nurs_dum = ifelse(grepl("Childcare facilities (preschool or other daycare)", Policy_subtarget, ignore.case = F), "Preschool or childcare facilities (generally for children ages 5 and below)", NA ),
    prim_dum = ifelse(grepl("Primary education", Policy_subtarget, ignore.case = F), "Primary Schools (generally for children ages 10 and below)", NA ),
    sec_dum = ifelse(grepl("Secondary education", Policy_subtarget, ignore.case = F), "Secondary Schools (generally for children ages 10 to 18)", NA ),
    high_dum = ifelse(grepl("Higher education", Policy_subtarget, ignore.case = F), "Higher education institutions (i.e. degree granting institutions)", NA )) %>%
  unite(type_sub_cat, nurs_dum, prim_dum, sec_dum, high_dum, na.rm = TRUE, sep = ',' ) %>%
  select(-c(2))
amp_coronanet_map = rows_patch(amp_coronanet_map, school_type, "unique_id")


4.3 Mass Gatherings

The following code maps how COVIDAMP captures restrictions of mass gathering policies to the CoronaNet taxonomy.

  • COVIDAMP and CoronaNet document whether a policy is targeted toward places of worship, prisons, and funeral homes but they use slightly different language to do so. The following extracts this information from the Policy_subtarget variable in the COVIDAMP taxonomy to determine what gathering type is being targeted into the type_sub_cat variable in the CoronaNet taxonom. These keywords were chosen based on a manual inspection of the COVIDAMP data.
temp = amp_coronanet_map %>%
  filter(type == "Restrictions of Mass Gatherings") %>%
  select(unique_id)
temp = covidamp[covidamp$unique_id %in% temp$unique_id,]
mass_type = temp %>%
  select(unique_id, Policy_subtarget) %>%
  mutate(
    relig_dum = ifelse(grepl("Churches/places of worship", Policy_subtarget, ignore.case = F), "Attendance at religious services restricted (e.g. mosque/church closings)", NA ),
    pris_dum = ifelse(grepl("Criminal justice system/prisons/jails/incarcerated persons", Policy_subtarget, ignore.case = F), "Prison population reduced (e.g. early release of prisoners)", NA ),
    fun_dum = ifelse(grepl("Funeral home/mortuary", Policy_subtarget, ignore.case = F), "Funerals and mourning rituals", NA )) %>%
  unite(type_sub_cat, relig_dum, pris_dum, fun_dum, na.rm = T, sep = ',' ) %>%
  select(-c(2))
amp_coronanet_map = rows_patch(amp_coronanet_map, mass_type, "unique_id") 


4.4 Vaccines

The following code maps how COVIDAMP captures vaccination policies to the CoronaNet taxonomy in more detail than the initial mapping shown above.

  • COVIDAMP and CoronaNet document whether a policy is targeted the administration, distribution, logistics and prioritization of COVID-19 vaccines but they use slightly different language to do so. The following maps this information from Policy_subtarget variable in the COVIDAMP taxonomy into the type_sub_cat variable in the CoronaNet taxonomy.
vaccine_sub = covidamp %>%
  filter(Policy_category == "Vaccinations") %>%
  select(unique_id, Policy_category, Policy_subcategory) %>%
  mutate(type_sub_cat = case_when(
    Policy_subcategory == "Vaccine administration, distribution, and logistics" ~ "Distribution of COVID-19 vaccines",
    Policy_subcategory == 'Vaccine prioritization' ~ "Distribution of COVID-19 vaccines",
    TRUE ~ as.character(NA)
  ))%>%
  select(-c(2,3))
amp_coronanet_map = rows_patch(amp_coronanet_map, vaccine, "unique_id")
>>>>>>> Stashed changes:RCode/collaboration/covidamp/COVIDAMP_coronanet_taxonomy.html