Heroku部署Shiny App:用base R/dplyr替代rowr::cbind.fill方案咨询
rowr::cbind.fill with Base R or dplyr Since you're hitting R version compatibility issues with rowr on Heroku, let's walk through how to replicate the behavior of rowr::cbind.fill using tools that are more widely supported (base R or dplyr/purrr).
First, let's recap what rowr::cbind.fill does: it takes multiple vectors (or data frames) of different lengths, pads the shorter ones with a fill value (default NULL, which becomes NA in practice) to match the longest input, then combines them column-wise into a data frame.
Option 1: Base R Implementation
You can replicate this logic directly in base R without any extra packages. Here's a function that mirrors the core behavior of cbind.fill:
cbind_fill_base <- function(..., fill = NA) { # Collect all input vectors/data frames into a list inputs <- list(...) # Calculate the maximum length across all inputs max_length <- max(sapply(inputs, function(x) if(is.data.frame(x)) nrow(x) else length(x))) # Pad each input to the maximum length with the fill value padded_inputs <- lapply(inputs, function(x) { if (is.data.frame(x)) { # If input is a data frame, pad rows with fill pad_rows <- max_length - nrow(x) if (pad_rows > 0) { padded_rows <- as.data.frame(lapply(x, function(col) rep(fill, pad_rows))) rbind(x, padded_rows) } else { x } } else { # If input is a vector, pad with fill to max length c(x, rep(fill, max_length - length(x))) } }) # Combine all padded inputs into a single data frame do.call(cbind.data.frame, padded_inputs) }
Example Usage:
# Test with vectors of different lengths vec1 <- 1:3 vec2 <- 4:6 vec3 <- 7:8 cbind_fill_base(vec1, vec2, vec3) # vec1 vec2 vec3 # 1 1 4 7 # 2 2 5 8 # 3 3 6 NA
This function handles both vectors and data frames as inputs, just like rowr::cbind.fill. It’s lightweight and requires no additional packages—perfect for avoiding compatibility headaches on Heroku.
Option 2: dplyr + purrr Implementation
If you’re already using the tidyverse in your Shiny app, this concise version uses dplyr and purrr to replicate the behavior:
library(dplyr) library(purrr) cbind_fill_dplyr <- function(..., fill = NA) { inputs <- list(...) # Get the maximum length across all inputs max_length <- inputs %>% map_int(function(x) if(is.data.frame(x)) nrow(x) else length(x)) %>% max() # Pad each input and convert to a tibble column padded_inputs <- inputs %>% map(function(x) { if (is.data.frame(x)) { pad_rows <- max_length - nrow(x) if (pad_rows > 0) { x %>% add_row(!!!set_names(rep(fill, ncol(x)), colnames(x))) } else { x } } else { tibble(col = x) %>% add_row(col = rep(fill, max_length - length(x))) } }) # Combine all columns into one tibble bind_cols(padded_inputs) }
Example Usage:
# Same test vectors as before cbind_fill_dplyr(vec1, vec2, vec3) # # A tibble: 3 × 3 # col1 col2 col3 # <int> <int> <int> # 1 1 4 7 # 2 2 5 8 # 3 3 6 NA
This version returns a tibble (tidyverse’s enhanced data frame), but you can convert it to a base data frame with as.data.frame() if needed.
Key Notes for Heroku Deployment
- Both implementations avoid the
rowrpackage entirely, so you won’t run into R version compatibility issues with Heroku’s buildpacks. - The base R version is dependency-free, keeping your deployment lightweight.
- The dplyr/purrr version integrates seamlessly if you’re already using tidyverse tools in your Shiny app.
内容的提问来源于stack exchange,提问作者J.Doe

