Laurent Rhelp
2024-May-24 19:35 UTC
[R] dplyr, group_by and selective action according to each group
Dear RHelp-list, ?? Using dplyr and the group_by approach on a dataframe, I want to be able to apply a specific action according to the group name. The code bellow works, but I am not able to write it in a more esthetic way using dplyr. Can somebody help me to find a better solution ? Thank you Best regards Laurent df_test <- data.frame( x1=1:9, x2=1:9, gr=rep(paste0("gr",1:3),each=3)) df_test? <-? df_test %>% dplyr::group_by(gr) %>% ? group_modify(.f=function(.x,.y){ ??? print(paste0("Nom du groupe : ",.y[["gr"]])) ??? switch(as.character(.y[["gr"]]) ?????????? , gr1 = {.x[,"x1"] <- .x[,"x1"]+1} ?????????? , gr2 = {.x[,"x1"] <- 0} ?????????? , gr3 = {.x[,"x1"] <- .x[,"x1"]+2} ?????????? , {stop(paste0('The group ',.y[["gr"]]," is not taken into account"))} ??? ) ??? return(.x) }) %>% ungroup() df_test
Bert Gunter
2024-May-24 22:52 UTC
[R] dplyr, group_by and selective action according to each group
Laurent: As I don't use dplyr, this won't help you, but I hope you and others may find it entertaining anyway. If I understand you correctly (and ignore this if I have not), there are a ton of ways to do this in base R, including using switch() along the lines you noted in your post. However, when the functions get sufficiently complicated or numerous, it may be useful to store them in a named list and use the names to call them in some sort of loop. Here I have just used your anonymous functions in the list, but of course you could have used already existing functions instead. ## your example df_test <- data.frame( x1=1:9, x2=1:9, gr=rep(paste0("gr",1:3),each=3)) ## function list with the relevant names funcs <- list(gr1 = \(x)x+1, gr2 = \(x)0, gr3 = \(x)x+2) ## Alternatively you could do this if you had many different functions: ## funcs <- list(\(x)x+1, \(x)0, \(x)x+2) ## names(funcs) <- sort(unique(df_test$gr)) ## note that sort() is unnecessary in your example, but I think that it would ## be helpful if you had a lot of different groups and corresponding functions ## to track. ##Now the little loop to call the functions df_test$x1 <- with(df_test,{ for(nm in names(funcs)) x1[gr == nm] <- funcs[[nm]](x1[gr == nm]) x1} ) ################# Note that the above uses one of the features that I really like about R -- functions are full first class objects that can be thrown around and handled just like any other "variables" . So funcs[[nm]](whatever) seems to me to be a natural way to choose and call the function you want. You may disagree, of course. Caveat: I make no claims about the efficiency or lack thereof of the above. Cheers, Bert On Fri, May 24, 2024 at 12:35?PM Laurent Rhelp <laurentRHelp at free.fr> wrote:> Dear RHelp-list, > > Using dplyr and the group_by approach on a dataframe, I want to be > able to apply a specific action according to the group name. The code > bellow works, but I am not able to write it in a more esthetic way using > dplyr. Can somebody help me to find a better solution ? > > Thank you > > Best regards > > Laurent > > df_test <- data.frame( x1=1:9, x2=1:9, gr=rep(paste0("gr",1:3),each=3)) > df_test <- df_test %>% dplyr::group_by(gr) %>% > group_modify(.f=function(.x,.y){ > print(paste0("Nom du groupe : ",.y[["gr"]])) > switch(as.character(.y[["gr"]]) > , gr1 = {.x[,"x1"] <- .x[,"x1"]+1} > , gr2 = {.x[,"x1"] <- 0} > , gr3 = {.x[,"x1"] <- .x[,"x1"]+2} > , {stop(paste0('The group ',.y[["gr"]]," is not taken into > account"))} > ) > return(.x) }) %>% ungroup() > > df_test > > ______________________________________________ > R-help at r-project.org mailing list -- To UNSUBSCRIBE and more, see > https://stat.ethz.ch/mailman/listinfo/r-help > PLEASE do read the posting guide > http://www.R-project.org/posting-guide.html > and provide commented, minimal, self-contained, reproducible code. >[[alternative HTML version deleted]]