如何在reactablefmtr中动态生成color_tiles列定义?
解决reactable中动态生成color_tiles列时着色统一引用最后一列的问题
你遇到的问题是R中闭包延迟绑定导致的——在for循环里创建的列定义,会共享循环变量i的最终值(也就是2),所以所有color_tiles的color_by都会指向最后一个class2列。
下面提供两种可行的解决方法:
方法1:用purrr::map代替for循环
map会为每个迭代创建独立的环境,避免变量共享问题:
library(reactable) library(reactablefmtr) library(dplyr) library(purrr) tile_column <- function(ref_column, name, show_text = FALSE) { # 不需要传入x,color_tiles会自动处理对应列的单元格数据 colDef( show = TRUE, name = name, cell = color_tiles( color_by = ref_column, colors = c("red", "orange", "yellow", "limegreen", "green"), box_shadow = TRUE, show_text = show_text ), na = "" ) } data <- tibble( name = paste("name", 1:10), val1 = paste("val1", 1:10), val2 = paste("val2", 1:10), class1 = sample(1:5, 10, replace = TRUE), class2 = sample(1:5, 10, replace = TRUE) ) col_definitions1 <- list( name = colDef(show = TRUE, name = "Name") ) # 用map生成列定义,每个迭代独立处理 col_definitions2 <- map(1:2, function(i) { tile_column( ref_column = paste0("class", i), name = paste("Column", i), show_text = TRUE ) }) %>% set_names(paste0("val", 1:2)) col_definitions <- c(col_definitions1, col_definitions2) data %>% reactable( defaultColDef = colDef(show = FALSE), columns = col_definitions )
方法2:在for循环中强制求值变量
如果坚持用for循环,可以用force()函数强制当前迭代的ref_column值被立即求值,避免延迟绑定:
library(reactable) library(reactablefmtr) library(dplyr) library(purrr) tile_column <- function(ref_column, name, show_text = FALSE) { colDef( show = TRUE, name = name, cell = color_tiles( color_by = ref_column, colors = c("red", "orange", "yellow", "limegreen", "green"), box_shadow = TRUE, show_text = show_text ), na = "" ) } data <- tibble( name = paste("name", 1:10), val1 = paste("val1", 1:10), val2 = paste("val2", 1:10), class1 = sample(1:5, 10, replace = TRUE), class2 = sample(1:5, 10, replace = TRUE) ) col_definitions1 <- list( name = colDef(show = TRUE, name = "Name") ) col_definitions2 <- list() for (i in 1:2) { ref_col <- paste0("class", i) force(ref_col) # 强制求值当前的ref_col col_definitions2 <- c( col_definitions2, list(tile_column(ref_column = ref_col, name = paste("Column", i), show_text = TRUE)) ) } col_definitions3 <- col_definitions2 |> set_names(paste0("val", 1:2)) col_definitions <- c(col_definitions1, col_definitions3) data %>% reactable( defaultColDef = colDef(show = FALSE), columns = col_definitions )
另外注意:原tile_column函数里的x参数是多余的,color_tiles作为cell参数时,会自动接收对应列的单元格数据,不需要手动传入整个数据集。
内容的提问来源于stack exchange,提问作者eastclintw00d
相关产品推荐
相关产品推荐

