0
votes

I am making my first baby steps with non standard evaluation (NSE) in dplyr. Consider the following snippet: it takes a tibble, sorts it according to the values inside a column and replaces the n-k lower values with "Other".

See for instance:

library(dplyr)

df <- cars%>%as_tibble

k <- 3

df2 <- df %>%
arrange(desc(dist))  %>% 
mutate(dist2 = factor(c(dist[1:k],
                rep("Other", n() - k)),
                levels = c(dist[1:k], "Other")))

What I would like is a function such that:

df2bis<-df %>% sort_keep(old_column, new_column, levels_to_keep)

produces the same result, where old_column column "dist" (the column I use to sort the data set), new_column (the column I generate) is "dist2" and levels_to_keep is "k" (number of values I explicitly retain). I am getting lost in enquo, quo_name etc...

Any suggestion is appreciated.

2
Do you want to keep k highest levels or any levels corresponding to the top k values in the vector? For example, for vector c(10, 10, 10, 10, 9, 8, 7, 6, 5), would you like to keep the levels 10, 9 and 8 or only 10? - Vlad C.
Have you checked out the forcats package? It's the tidyverse package that's for working with factors. - MrFlick
Hi! In c(10, 10, 10, 10, 9, 8, 7, 6, 5) I would like to keep 10, 9 and 8. In my data I have continuous numbers and repetitions do not occur, which is why I did not think about this. I really would like to translate that code into a dplyr function (to be able to reuse it). - larry77

2 Answers

1
votes

You can do:

library(dplyr)

sort_keep=function(df,old_column, new_column, levels_to_keep){
  old_column = enquo(old_column)
  new_column = as.character(substitute(new_column))
  df %>%
    arrange(desc(!!old_column))  %>% 
    mutate(use = !!old_column,
           !!new_column := factor(c(use[1:levels_to_keep],
                                  rep("Other", n() - levels_to_keep)),
                                levels = c(use[1:levels_to_keep], "Other")),
           use=NULL)
}


 df%>%sort_keep(dist,dist2,3)
0
votes

Something like this?

old_column = "dist"
new_column = "dist2"
levels_to_keep = 3

command = "df2bis<-df %>% sort_keep(old_column, new_column, levels_to_keep)"
command = gsub('old_column', old_column, command)
command = gsub('new_column', new_column, command)
command = gsub('levels_to_keep', levels_to_keep, command)
eval(parse(text=command))