Mike
Mike

Reputation: 2097

Struggling with how to incorporate a reordering of dataframe rows based on a Vector within my function

library(tidyverse)
library(ggplot2) for diamonds dataset

I'm having trouble getting my function to work. What I'm trying to do, using the diamonds dataset form ggplot2 for this example, is to dplyr::group_by "cut" and "color", then dplyr::summarise to get counts. I used rlang and purrr to output both summaries of counts into list, then rename one of the columns, and bind them with dplyr::map_df. Finally, I want to reorder the "Cut" column based on another vector called "Order". The function works until I try to incorporate the row reordering...

This might not make sense for this data, but this is just for an example and it makes sense for my real data.

Anyways, the code below works...

Groups<-list("cut","color")

 Groups<-Groups%>%
 map_df(function(group){

     syms<-syms(group)

     diamonds%>%
         group_by(!!!syms)%>%
         summarise(Count=n())%>%
         set_names(c("Cut","Count"))
 })

And next, I want to reorder the rows based on the "Order" vector, which also works.

Order<-c("Good","Very Good","Premium","Ideal","Fair","E","F","G","D","H","J","I")

Groups%>%slice(match(Order, Cut))

However, this is where I'm stuck. I'm trying to do all this in one function, but it doesn't seem to work. I feel like I'm missing something small...

Fun<-function(df){

Order<-c("Good","Very Good","Premium","Ideal","Fair","E","F","G","D","H","J","I")

Groups<-list("cut","color")

 Groups<-Groups%>%
 map_df(function(group){

     syms<-syms(group)

     df%>%
         group_by(!!!syms)%>%
         summarise(Count=n())%>%
         set_names(c("Cut","Count"))%>%
         slice(match(Order,Cut))
return(df)
})
}

Here is another attempt...

Fun<-function(df){

Order<-c("Good","Very Good","Premium","Ideal","Fair","E","F","G","D","H","J","I")

Groups<-list("cut","color")

 Groups<-Groups%>%
 map_df(function(group){

     syms<-syms(group)

     df%>%
         group_by(!!!syms)%>%
         summarise(Count=n())%>%
         set_names(c("Cut","Count"))

df<-df%>%slice(match(Order,Cut))
return(df)
})
}

What am I missing here?

Upvotes: 4

Views: 133

Answers (3)

akrun
akrun

Reputation: 887531

We don't need to apply syms within a loop. It can take a vector/list of length greater than 1 and convert it to symbols. Therefore, loop through the syms and then use map to do the group_by on each symbol object

Fun<-function(df){

Order<-c("Good","Very Good","Premium","Ideal","Fair","E","F","G","D","H","J","I")

Groups<-list("cut","color")

Groups %>%
       syms %>%
       map_df(~ df %>%
               group_by(!!!  .x) %>%
               summarise(Count=n()) %>%
               set_names(c("Cut","Count")) %>%
               slice(match(Order,Cut)) #%>%                    
               #mutate(Cut = as.character(Cut)) 
               #to avoid the warning coercion of factor to character 


      )




}

Fun(diamonds)
# A tibble: 12 x 2
#   Cut       Count
#   <chr>     <int>
# 1 Good       4906
# 2 Very Good 12082
# 3 Premium   13791
# 4 Ideal     21551
# 5 Fair       1610
# 6 E          9797
# 7 F          9542
# 8 G         11292
# 9 D          6775
#10 H          8304
#11 J          2808
#12 I          5422

Upvotes: 3

MKR
MKR

Reputation: 20095

The possible correction to the problem. For the simplicity I have created a temp_df variable and returned the same.

Fun<-function(df){

  Order<-c("Good","Very Good","Premium","Ideal","Fair","E","F","G","D","H","J","I")

  Groups<-list("cut","color")

  Groups<-Groups%>%
    map_df(function(group){

      syms<-syms(group)

      temp <- df%>%
        group_by(!!!syms)%>%
        summarise(Count=n())%>%
        set_names(c("Cut","Count"))
    })

  temp_df <- Groups%>%slice(match(Order, Cut))
  return(temp_df)
}

> x <- Fun(diamonds)
> x
# A tibble: 12 x 2
   Cut       Count
   <chr>     <int>
 1 Good       4906
 2 Very Good 12082
 3 Premium   13791
 4 Ideal     21551
 5 Fair       1610
 6 E          9797
 7 F          9542
 8 G         11292
 9 D          6775
10 H          8304
11 J          2808
12 I          5422

Upvotes: 1

gatsky
gatsky

Reputation: 1285

Your first attempt at Fun works except that the results are allocated to the Group variable and not returned. Try the following

Fun<-function(df){

Order<-c("Good","Very Good","Premium","Ideal","Fair","E","F","G","D","H","J","I")

Groups<-list("cut","color")

 Groups%>%
 map_df(function(group){

     syms<-syms(group)

     df%>%
         group_by(!!!syms)%>%
         summarise(Count=n())%>%
         set_names(c("Cut","Count"))%>%
         slice(match(Order,Cut))
return(df)
})
}

Fun(diamonds)

Upvotes: 2

Related Questions