Reputation: 2097
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
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
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
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