Home > Software engineering >  How to specify column index to mutate across using dplyr when table size is variable?
How to specify column index to mutate across using dplyr when table size is variable?

Time:04-01

I use a version of the example code below to convert table values to percentages. The problem I am having is this code is deployed in a Shiny app where the table size reactively expands/contracts (by both columns and rows) based on user input, and even the left-most column header (the "To" column header in this data frame example) changes reactively based on user input.

How do I change the column references in the mutate(across()) statement below from "To" and "Sum", to simply the first column and last column of the dataframe?

This code works fine for the static data frame shown below, but not for a dynamic data frame rendered in Shiny.

Example code:

library(tidyverse)

data <- 
  data.frame(
    To = c("A","B","C"),
    A = c(1,2,4),
    B = c(3,4,5),
    C = c(5,6,7)
  )

data <- data %>% 
  replace(is.na(.), 0) %>%
  bind_rows(summarise_all(., ~(if(is.numeric(.)) sum(.) else "Sum")))
data <- cbind(data, Sum = rowSums(data[,-1]))

data %>%
  mutate(across(-c(To), ~ ./.[To == "Sum"]))

CodePudding user response:

To exclude the first column you could simply use -1. And as the Sum is contained in the last row you could divide by .x[length(.x)]:

library(tidyverse)

data %>%
  mutate(across(-1, ~ .x / .x[length(.x)]))
#>    To         A         B         C       Sum
#> 1   A 0.1428571 0.2500000 0.2777778 0.2432432
#> 2   B 0.2857143 0.3333333 0.3333333 0.3243243
#> 3   C 0.5714286 0.4166667 0.3888889 0.4324324
#> 4 Sum 1.0000000 1.0000000 1.0000000 1.0000000
  • Related