简体   繁体   中英

summarising char and numerical dataframe with dplyr

I'm trying to summarise a dataframe using two variables - I basically want to break down variable 1 by variable 2 in order to plot the results in a 100% stacked bar chart.

I have multiple columns of type char and multiple columns of type numeric, which can be split between two main categories that will be used to create the breakdown.

I have tried to use gather from dplyr to transform the dataframe to longform, however the output is not what I expect.

variable1_by_variable2 <- function (dataset, variable_1) {

  #select variables columns - variable 1 columns are char, variable 2 
  #columns are numeric

  variable_1_columns <- dataset[, data.table::`%like%`(names(dataset), variable_1)]
  variable_2_columns <- dataset[, c('e_j', 'e_t', 'e_f', 'e_s', 'e_d', 'e_a')]

  #create new dataframe including only relevant columns
  df <- cbind(variable_1_columns, emotions_columns)
  df[c('e_j', 'e_t', 'e_f', 'e_s', 'e_d', 'e_a')] <-
       lapply(df[c('e_j', 'e_t', 'e_f', 'e_s', 'e_d', 'e_a')], 
              as.numeric)

  #transform df to long form
  new_df <- tidyr::gather(df, variable_2_columns, count, names(variable_2_columns[1]):names(variable_2_columns)[length(names(variable_2_columns))], factor_key=FALSE)
  t_names <- names(variable_1_columns)

  #count topics
  t_count <- function (x) {
    t <- sum(x == TRUE)
  }

  #group by variable 2 and count
  new_df <- new_df %>%
    dplyr::group_by(variable_2_columns) %>%
    dplyr::summarise_at(t_names, .funs = t_count)

  #transform new_df to longform
  final_df <- tidyr::gather(new_df, t, volume, names(variable_1_columns[1]):names(variable_1_columns)[length(names(variable_1_columns))], factor_key=FALSE)
  final_df <- data.frame(final_df)
  return (final_df)
}

This is the dataset I'm using:

structure(list(var_a = c("TRUE", "TRUE", "TRUE", 
"TRUE", "TRUE", "TRUE", "TRUE", "TRUE", "FALSE", "FALSE", "FALSE", 
"FALSE", "FALSE", "FALSE", "FALSE", "FALSE", "FALSE", "FALSE", 
"FALSE", "FALSE", "FALSE", "FALSE", "FALSE", "FALSE", "FALSE", 
"FALSE", "FALSE", "FALSE", "FALSE", "TRUE", "TRUE", "TRUE", "TRUE", 
"TRUE", "TRUE", "TRUE", "TRUE", "TRUE", "TRUE"), var_b = c("FALSE", 
"FALSE", "TRUE", "TRUE", "TRUE", "TRUE", "TRUE", "TRUE", "TRUE", 
"TRUE", "TRUE", "TRUE", "TRUE", "TRUE", "TRUE", "TRUE", "TRUE", 
"TRUE", "TRUE", "TRUE", "TRUE", "TRUE", "TRUE", "TRUE", "TRUE", 
"TRUE", "TRUE", "TRUE", "TRUE", "TRUE", "TRUE", "TRUE", "TRUE", 
"TRUE", "TRUE", "FALSE", "FALSE", "FALSE", "FALSE"), var_c = c("FALSE", 
"FALSE", "FALSE", "FALSE", "FALSE", "FALSE", "FALSE", "FALSE", 
"FALSE", "FALSE", "FALSE", "FALSE", "FALSE", "FALSE", "FALSE", 
"FALSE", "FALSE", "TRUE", "TRUE", "TRUE", "TRUE", "TRUE", "TRUE", 
"TRUE", "TRUE", "TRUE", "TRUE", "TRUE", "TRUE", "TRUE", "TRUE", 
"TRUE", "TRUE", "TRUE", "TRUE", "TRUE", "TRUE", "TRUE", "TRUE"
), var_d = c("FALSE", "FALSE", "FALSE", "FALSE", "FALSE", 
"FALSE", "FALSE", "FALSE", "FALSE", "FALSE", "FALSE", "FALSE", 
"FALSE", "FALSE", "FALSE", "FALSE", "TRUE", "TRUE", "TRUE", "TRUE", 
"TRUE", "TRUE", "TRUE", "TRUE", "TRUE", "TRUE", "TRUE", "TRUE", 
"TRUE", "TRUE", "TRUE", "TRUE", "TRUE", "TRUE", "TRUE", "TRUE", 
"TRUE", "TRUE", "TRUE"), var_e = c("FALSE", "FALSE", 
"FALSE", "FALSE", "FALSE", "FALSE", "FALSE", "FALSE", "FALSE", 
"FALSE", "FALSE", "FALSE", "FALSE", "FALSE", "FALSE", "FALSE", 
"FALSE", "TRUE", "TRUE", "TRUE", "TRUE", "TRUE", "TRUE", "TRUE", 
"TRUE", "TRUE", "TRUE", "TRUE", "TRUE", "TRUE", "TRUE", "TRUE", 
"TRUE", "TRUE", "TRUE", "TRUE", "TRUE", "TRUE", "TRUE"), var_f = c("FALSE", 
"FALSE", "FALSE", "FALSE", "FALSE", "FALSE", "FALSE", "FALSE", 
"TRUE", "TRUE", "TRUE", "TRUE", "TRUE", "TRUE", "TRUE", "TRUE", 
"TRUE", "TRUE", "TRUE", "TRUE", "TRUE", "TRUE", "TRUE", "TRUE", 
"TRUE", "TRUE", "TRUE", "TRUE", "TRUE", "TRUE", "TRUE", "TRUE", 
"TRUE", "TRUE", "TRUE", "TRUE", "TRUE", "TRUE", "TRUE"), e_j = c(0.5, 
NaN, 0, 0.333333333333333, 0.333333333333333, 0.5, 0, 0, 1, 1, 
0.666666666666667, NaN, 0, NaN, 0.5, 0.333333333333333, 0.333333333333333, 
0, 0, 0, 0, 0.5, 0.333333333333333, 0, 0, 1, 0, 0.333333333333333, 
0, NaN, 0.25, 0.5, 0.5, 0, 0, 0.5, 0.333333333333333, 0.5, 0.5
), e_t = c(0.5, NaN, 0, 0.666666666666667, 0.666666666666667, 
0.5, 1, 0.333333333333333, 0, 0, 0.333333333333333, NaN, 1, NaN, 
0.5, 0.666666666666667, 0.333333333333333, 0.25, 1, 1, 0.333333333333333, 
0.5, 0.666666666666667, 1, 1, 0, 1, 0.666666666666667, 0, NaN, 
0.25, 0.5, 0.5, 0.4, 0, 0.5, 0.5, 0.5, 0.5), fear = c(0, NaN, 
0.5, 0, 0, 0, 0, 0.333333333333333, 0, 0, 0, NaN, 0, NaN, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NaN, 0, 0, 0, 0.2, 
0, 0, 0, 0, 0), e_s = c(0, NaN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
NaN, 0, NaN, 0, 0, 0.166666666666667, 0.5, 0, 0, 0.333333333333333, 
0, 0, 0, 0, 0, 0, 0, 0.75, NaN, 0.25, 0, 0, 0.2, 0.5, 0, 0, 0, 
0), e_d = c(0, NaN, 0, 0, 0, 0, 0, 0, 0, 0, 0, NaN, 0, NaN, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, NaN, 0, 0, 0, 0, 
0, 0, 0, 0, 0), e_a = c(0, NaN, 0.5, 0, 0, 0, 0, 0.333333333333333, 
0, 0, 0, NaN, 0, NaN, 0, 0, 0.166666666666667, 0.25, 0, 0, 0.333333333333333, 
0, 0, 0, 0, 0, 0, 0, 0.25, NaN, 0.25, 0, 0, 0.2, 0.5, 0, 0.166666666666667, 
0, 0)), row.names = c(NA, -39L), class = "data.frame")

The desired output would be the following, however when I use gather the volume figure is the total number of rows and is repeated across all categories. The numeric values would be the average of each variable for a specific category (for example average of 'e_j' where 'a' is TRUE in the dataset)

  e_j    e_t    e_f    e_s     e_a    e_d           category
1 0.31   0.54   0.00   0.09    0.05   0.00              a
2 0.28   0.50   0.03   0.09    0.09   0.00              b
3 0.25   0.52   0.01   0.12    0.09   0.00              c
4 0.25   0.51   0.00   0.12    0.10   0.00              d
5 0.25   0.52   0.01   0.12    0.09   0.00              e
6 0.32   0.49   0.00   0.09    0.07   0.00              f

Not sure how you calculated your expected output, but you can try

library(tidyverse)
df %>% 
  as_tibble() %>% 
  gather(var, v, -e_j:-e_a) %>% 
  select(-fear) %>% 
  filter(v == "TRUE") %>% 
  group_by(var) %>% 
  summarise_at(vars(e_j:e_a), mean, na.rm = T)
# A tibble: 6 x 6
  var     e_j   e_t    e_s   e_d    e_a
  <chr> <dbl> <dbl>  <dbl> <dbl>  <dbl>
1 var_a 0.297 0.457 0.0594     0 0.122 
2 var_b 0.281 0.502 0.09       0 0.0928
3 var_c 0.250 0.527 0.121      0 0.0929
4 var_d 0.254 0.518 0.123      0 0.0962
5 var_e 0.250 0.527 0.121      0 0.0929
6 var_f 0.324 0.496 0.0964     0 0.0756

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM