R:根据条件隐藏 DT::datatable 中的单元格

R: hide cells in DT::datatable based on condition

我正在尝试创建一个包含子行的数据table:用户将能够单击一个名称并查看与该名称相关的链接列表。但是,每个名称显示的项目数量不同。

> data1 <- data.frame(name = c("John", "Maria", "Afonso"),
                      a = c("abc", "def", "rty"),
                      b=c("ghj","lop",NA),
                      c=c("zxc","cvb",NA),
                      d=c(NA, "mko", NA))
> data1
    name   a    b    c    d
1   John abc  ghj  zxc <NA>
2  Maria def  lop  cvb  mko
3 Afonso rty <NA> <NA> <NA>

我正在使用 varsExplore::datatable2 隐藏特定列:

varsExplore::datatable2(x=data1,  vars=c("a","b","c","d"))

并产生以下结果

是否可以修改 DT::datatable 以便仅呈现非“空”的单元格?因此,例如,如果有人单击“Afonso”,table 将只呈现“rty”,从而隐藏其他列(对于该行)的“空”值,同时如果用户仍然显示这些列单击“Maria”(没有任何“null”)。

(我应该尝试不同的方法来实现这种行为吗?)

varsExplore::datatable2

的内部工作一览

根据您的要求,我查看了 varsExplore::datatable2 源代码。我发现 varsExplore::datatable2 调用 varsExplore:::.callback2(3: 表示它不是导出函数)来创建 javascript 代码。此函数还调用 varsExplore:::.child_row_table2 其中 returns 一个 javascript 函数 format(row_data) 将行数据格式化为您看到的 table。

建议的解决方案

我只是用我的 js 知识来改变 varsExplore:::.child_row_table2 的输出,我想出了以下结果:

.child_row_table2 <- function(x, pos = NULL) {

  names_x <- paste0(names(x), ":")
  text <- "
  var format = function(d) {
    text = '<div><table >' +
  "

  for (i in seq_along(pos)) {
    text <- paste(text, glue::glue(
      " (  d[{pos[i]}]!==null ? ( '<tr>' +   
          '<td>' + '{names_x[pos[i]]}' + '</td>' +
          '<td>' + d[{pos[i]}] + '</td>' +
        '</tr>' ) : '' ) + " ))
  }

  paste0(text,
         "'</table></div>'
      return text;};"
  )
}

我所做的唯一更改是添加 d[{pos[i]}]!==null ? ....... : '',它只会在其值 d[pos[i]] 不为空时显示列 pos[i]


考虑到加载包并将函数添加到全局环境并不能解决问题,我在 github 上进行了分叉并提交了更改,您现在可以通过 [=71 安装它了=](github repo 是一个 read-only cran mirror 无法提交拉取请求)

devtools::install_github("moutikabdessabour/varsExplore")

编辑

如果您不想重新下载包,我基本上找到了一个解决方案,您需要覆盖 datatable2 函数:

  • 首先将源代码复制到位于 path/to/your/Rfile
  • 的 R 文件中
# the data.table way
data.table::fwrite(list(capture.output(varsExplore::datatable2)), quote=F, sep='\n', file="path/to/your/Rfile", append=T)

# the baseR way
fileConn<-file("path/to/your/Rfile", open='a')
writeLines(capture.output(varsExplore::datatable2), fileConn)
close(fileConn)
  • 那你就得用最后一根线代替
DT::datatable(
  x, 
  ..., 
  escape = -2, 
  options = opts, 
  callback = DT::JS(.callback2(x = x, pos = c(0, pos))) 
)

与 :

DT::datatable(
  x,
  ...,
  escape = -2,
  options = opts,
  callback = DT::JS(gsub("('<tr>.+?(d\[\d+\]).+?</tr>')" , "(\2==null ? '' : \1)", varsExplore:::.callback2(x = x, pos = c(0, pos))))
)

这段代码主要做的是使用正则表达式添加 js 条件。

结果