Packages

library(tidyverse)
library(repurrrsive)
library(jsonlite)
library(janitor)

Exercise 1

Problem

Using sw_people in package repurrrsive, extract the name of all characters using:

  • a for loop,

  • an apply function.

str(sw_people[[1]])
#> List of 16
#>  $ name      : chr "Luke Skywalker"
#>  $ height    : chr "172"
#>  $ mass      : chr "77"
#>  $ hair_color: chr "blond"
#>  $ skin_color: chr "fair"
#>  $ eye_color : chr "blue"
#>  $ birth_year: chr "19BBY"
#>  $ gender    : chr "male"
#>  $ homeworld : chr "http://swapi.co/api/planets/1/"
#>  $ films     : chr [1:5] "http://swapi.co/api/films/6/" "http://swapi.co/api/films/3/" "http://swapi.co/api/films/2/" "http://swapi.co/api/films/1/" ...
#>  $ species   : chr "http://swapi.co/api/species/1/"
#>  $ vehicles  : chr [1:2] "http://swapi.co/api/vehicles/14/" "http://swapi.co/api/vehicles/30/"
#>  $ starships : chr [1:2] "http://swapi.co/api/starships/12/" "http://swapi.co/api/starships/22/"
#>  $ created   : chr "2014-12-09T13:50:51.644000Z"
#>  $ edited    : chr "2014-12-20T21:17:56.891000Z"
#>  $ url       : chr "http://swapi.co/api/people/1/"

Hint: The [ and [[ are functions.

Solution

Using a for loop:

out <- character(length = length(sw_people))

for (i in seq_along(sw_people)) {
  out[i] <- sw_people[[i]]$name
}

Using sapply():

s_out <- sapply(sw_people, `[[`, "name")

Exercise 2

Problem

Use mtcars and a single map or map variant to

  1. get the type of each variable,

  2. get the fourth row such that result is a character vector,

  3. compute the mean of each variable, and

  4. compute the mean and median for each variable such that the result is a data frame with the mean values in row 1 and the median values in row 2.

Solution

The solutions to 1, 2, 3, 4 are given below by each line of code, respectively.

map_chr(mtcars, typeof)
#>      mpg      cyl     disp       hp     drat       wt     qsec       vs 
#> "double" "double" "double" "double" "double" "double" "double" "double" 
#>       am     gear     carb 
#> "double" "double" "double"
map_chr(mtcars, 4)
#>          mpg          cyl         disp           hp         drat           wt 
#>  "21.400000"   "6.000000" "258.000000" "110.000000"   "3.080000"   "3.215000" 
#>         qsec           vs           am         gear         carb 
#>  "19.440000"   "1.000000"   "0.000000"   "3.000000"   "1.000000"
map_dbl(mtcars, mean)
#>        mpg        cyl       disp         hp       drat         wt       qsec 
#>  20.090625   6.187500 230.721875 146.687500   3.596563   3.217250  17.848750 
#>         vs         am       gear       carb 
#>   0.437500   0.406250   3.687500   2.812500
map_df(mtcars, ~ c(mean(.), median(.)))

Exercise 3

Problem

Use a map function and your mh_distance() function from Homework 01 to iterate over both vectors s and w below.

s <- c(26, 50123, 456.12, 8, 0)
w <- c(22, 50000, 451.00, 88, 0)

Solutions

mh_distance <- function(x, y) {
  # check for correct modes
  disallow_modes <- c("complex", "raw")
  
  if (mode(x) != mode(y) || any(c(mode(x), mode(y)) %in% disallow_modes)) {
    warning("x and y are not both logical, numeric, or character")
    return(-1)
  }
  
  # check not NA, NaN, Inf, -Inf
  if (any(c(is.na(c(x, y)), is.infinite(c(x, y))))) {
    warning("x or y cannot be NA, NaN, Inf, or -Inf")
    return(-1)
  }
  
  # check not decimal
  # if logical or numeric, convert to character
  if (!is.character(x)) {
    x <- abs(as.numeric(x))
    y <- abs(as.numeric(y))
    
    if (any(c(x, y) %/% 1 != c(x, y))) {
      warning("x or y cannot contain decimal values")
      return(-1)
    }
    
    x <- as.character(x)
    y <- as.character(y)
  }
  
  # check same number of digits or letters
  # x and y are both of type character at this step
  if (nchar(x) != nchar(y)) {
    warning("x and y do not have the same number of digits or letters")
    return(-1)
  }
  
  # parse at each letter or number
  x_split <- unlist(strsplit(x, split = ""))
  y_split <- unlist(strsplit(y, split = ""))
  
  return(sum(x_split != y_split))
}
s <- c(26, 50123, 456.12, 8, 0)
w <- c(22, 50000, 451.00, 88, 0)

map2_dbl(s, w, ~ suppressWarnings(mh_distance(x = .x, y = .y)))
#> [1]  1  3 -1 -1  0

Exercise 4

Consider the object senators below.

json_file <- "https://www.govtrack.us/api/v2/role?current=true&role_type=senator"
senators <- read_json(json_file)

Problem

Use one of the map_*() variants to get

  1. the name of each senator as a character vector (preview given below),
#> [1] "Sen. Michael “Mike” Crapo [R-ID]"    
#> [2] "Sen. Charles “Chuck” Grassley [R-IA]"
#> [3] "Sen. Patrick Leahy [D-VT]"           
#> [4] "Sen. Lisa Murkowski [R-AK]"          
#> [5] "Sen. Patty Murray [D-WA]"
  1. the name of each senator as a list (preview given below),
#> [[1]]
#> [1] "Sen. Michael “Mike” Crapo [R-ID]"
#> 
#> [[2]]
#> [1] "Sen. Charles “Chuck” Grassley [R-IA]"
#> 
#> [[3]]
#> [1] "Sen. Patrick Leahy [D-VT]"
  1. the description and party of each senator as a data frame (preview given below)

Solution

Part 1

map_chr(senators$objects, list("person", "name"))

Part 2

map(senators$objects, list("person", "name"))

Part 3

map_df(senators$objects, `[`, c("description", "party"))