runningbirds
runningbirds

Reputation: 6605

Calculate mode for each column in dataframe using lapply dplyr

I'm trying to create a function that essentially gets me the MODE...or MODE-X (2nd-Xth most common value & and the associated counts for each column in a data frame.

I can't figure out what I may be missing and I'm looking for some assistance? I believe it has to do with the passing in of a variable into dplyr function.

library(tidyverse)


myfunct_get_mode = function(x, rank=1){

  mytable = dplyr::count(rlang::sym(x), sort = TRUE)
  names(mytable)= c('variable','counts')
  # return just the rank specified...such as mode or mode -1, etc
  result = table %>% dplyr::slice(rlang::sym(rank))
  return(result)
}

mtcars %>% lapply(. %>% (function(x) myfunct_get_mode(x, rank=2)))

Upvotes: 0

Views: 748

Answers (2)

kath
kath

Reputation: 7724

There are some problems with your function:

  1. You function-call is not doing what you think. Check with mtcars %>% lapply(. %>% (function(x) print(x))) that actually your x is the whole column of mtcars. To get the names of the column apply the function to names(mtcars). But then you also have to specify the dataframe you're working on.
  2. To evaluate a symbol you get sym from you need to use !! in front of the rlang::sym(x).
  3. rank is not a variable name, thus no need for rlang::sym here.
  4. table should be mytable in second to last line of your function.

So how could it work (although there are probably better ways):

myfunct_get_mode = function(df, x, rank=1){

  mytable = count(df, !!rlang::sym(x), sort = TRUE)
  names(mytable)= c('variable','counts')
  # return just the rank specified...such as mode or mode -1, etc
  result = mytable %>% slice(rank)
  return(result)
}

names(mtcars) %>% lapply(function(x) myfunct_get_mode(mtcars, x, rank=2))

Upvotes: 1

akrun
akrun

Reputation: 886938

If we need this in a list, we can use map

f1 <- function(dat, rank = 1) {
        purrr::imap(dat, ~
                         dat %>%
                            count(!! rlang::sym(.y)) %>%
                            rename_all(~ c('variable', 'counts')) %>%
                            arrange(desc(counts)) %>%
                            slice(seq_len(rank))) #%>%
        #bind_cols - convert to a data.frame

}

f1(mtcars, 2)

Upvotes: 0

Related Questions