Reproducing function to create data frame in R - Reproducible Code

Viewed 76

Goals: To discover diamond similarities in the diamonds set. Also, to create a row for each diamond name (auto-populated via the states set) that includes similarity columns for each diamond.

Example of desired outcome

Work: Below, I created a function that uses dplyr to discover diamond similarity by inputting the diamond's name into the function and filtering for similar attributes.

Issue: My function works, but it can only handle one diamond name at a time. I am stuck on how to reiterate my function over the entire list of names. Ideally this iteration would return a data frame of each unique diamond name along with its similar attributes.I have tried writing a second function that uses a for loop to iterate the list of names, but to no avail. Any advice would be greatly appreciated.

library(tidyverse)
diamonds <- diamonds[1:50,]
# I wanted to give each diamond a unique name, so I am using the states set to populate names.
diamonds$name <- state.name
diamonds

f_comp <- function(df = diamonds, name_insert, name_c = name, carat_c = carat, depth_c = depth, price_c = price){

  name_c <- enquo(name_c)
  carat_c <- enquo(carat_c)
  depth_c <- enquo(depth_c)
  price_c <- enquo(price_c)

  #filter by specifc diamond name)
  n <- df %>%
      filter(name_insert == !! name_c)

  #filtering by carat size, then measuring distance with mutate
  prox <-  df %>%
    filter(!! carat_c <= n$carat +.04 & !! carat_c >= n$carat -.04) %>%
    mutate(scores = abs(!! depth_c - n$depth) + abs(!! price_c - n$price)) %>%
    arrange(scores)

  #return avg scores of top 3 (ascending)
  prox1 <- prox[1:3,] 
  prox1 <- prox1 %>%
    mutate(avg_score = (mean(scores)))

  #format 
  prox1  <- prox1 %>%
    select(name, avg_score) %>%
    mutate(nm1 = name[2], nm2 = name[3]) 

  #Return one row w/ avg score
  prox_db <- prox1[1,]
}

test_alaska <- f_comp(name_insert = "Alaska")

*#Everything works until I try to add the second function that reiterates the name column*

  func2 <- function(d) {
    storage <- data.frame()
    for(i in d) {
      storage[i] <- f_comp(name_insert = i)
      storage
    }  
  }

test_5 <- func2(d = diamonds$name)
1 Answers

The function needs a small modification in filter. Instead of enquo + !! an option is {{}}

library(dplyr)
library(purrr)
library(ggplot2)

f_comp <- function(df = diamonds, name_insert,
  name_c = name, carat_c = carat, depth_c = depth, price_c = price){

   name_c <- enquo(name_c)
   carat_c <- enquo(carat_c)
   depth_c <- enquo(depth_c)
   price_c <- enquo(price_c)

   #filter by specifc diamond name)
   n <- df %>%
       filter(!! name_c  == name_insert) # changed here






 #filtering by carat size, then measuring distance with mutate
 prox <-  df %>%
   filter(!! carat_c <= n$carat +.04 & !! carat_c >= n$carat -.04) %>%
   mutate(scores = abs(!! depth_c - n$depth) + abs(!! price_c - n$price)) %>%
   arrange(scores)

 #return avg scores of top 3 (ascending)
 prox1 <- prox[1:3,] 
 prox1 <- prox1 %>%
   mutate(avg_score = (mean(scores)))

 #format 
 prox1  <- prox1 %>%
   select(name, avg_score) %>%
   mutate(nm1 = name[2], nm2 = name[3]) 

 #Return one row w/ avg score
 prox_db <- prox1[1,]
 prox_db

 }

-testing

f_comp(name_insert = "Alaska")
# A tibble: 1 x 4
#  name   avg_score nm1     nm2    
#  <chr>      <dbl> <chr>   <chr>  
#1 Alaska      1.87 Alabama Arizona

with multiple 'name's

map_dfr(unique(diamonds$name), ~ f_comp(name_insert = .x))
# A tibble: 50 x 4
#   name        avg_score nm1         nm2        
# * <chr>           <dbl> <chr>       <chr>      
# 1 Alabama         2.43  Alaska      Arizona    
# 2 Alaska          1.87  Alabama     Arizona    
# 3 Arizona         3.17  Alaska      Alabama    
# 4 Arkansas        1.80  California  Delaware   
# 5 California      2.2   Arkansas    Hawaii     
# 6 Colorado        0.800 Connecticut Delaware   
# 7 Connecticut     0.633 Colorado    Delaware   
# 8 Delaware        1.10  Connecticut Colorado   
# 9 Florida         2.17  Delaware    Colorado   
#10 Georgia         2.80  Delaware    Connecticut
# … with 40 more rows
Related