【问题标题】:What is the optimal approach for handling multiple Tables in R which are connected?处理 R 中连接的多个表的最佳方法是什么?
【发布时间】:2020-04-17 21:00:07
【问题描述】:
library(data.table)

如果您在星型模式中有 3 个表。像这样的东西。我有一个虚拟表 dt1 取决于 dt2 和 dt3

dt1 <- data.table( x1 = 1:10, y1 = 11:20)
dt2 <- data.table( x2 = 1:10, y2 = letters[11:20])
dt3 <- data.table( x3 = letters[1:10], y3 = 11:20)

dt1[dt2, on = c( x1 = "x2")]
dt2[dt1, on = c( x2 = "x1")]
dt3[dt1, on = c( y3 = "y1")]

在上述场景中,您必须为每个查询记住近 4 种组合。连同他们的订单。想象一个场景,您有 10 或 20 个直接来自数据库或 csv 的此类表。

dt1[dt2]
dt2[dt1]
dt1[dt3]
dt3[dt1]

一种方法是编写这样的函数。

rememberJoin <- function(table1, table2){
  if( 
    table1 == "dt1" && 
    table2 == "dt2"
  ){
    return(c( x1 = "x2"))
  } else if(
    table1 == "dt2" && 
    table2 == "dt1"
  ){
    return(c( x2 = "x1"))
  } else if(
    table1 == "dt3" && 
    table2 == "dt1"
  ){
    return(c( y3 = "y1"))
  } else if(
    table1 == "dt1" && 
    table2 == "dt3"
  ){
    return(c( y1 = "y3"))
  }
}


dt1[dt2, on = rememberJoin("dt1", "dt2")]
dt2[dt1, on = rememberJoin("dt2", "dt1")]
dt3[dt1, on = rememberJoin("dt3", "dt1")]

但是整个解决方案很老套,if 语句太多,而且很难阅读或调试。我通过创建命名列表使用了另一种解决方案。

Join <- list(
dt1dt2 = c( x1 = "x2"),
dt2dt1 = c( x2 = "x1"),
dt3dt1 = c( y3 = "y1"),
dt1dt3 = c( y1 = "y3")
)

dt1[dt2, on = Join$dt1dt2]
dt2[dt1, on = Join$dt2dt1]
dt3[dt1, on = Join$dt3dt1]

它工作得很好。但我仍然不确定这是否是最佳解决方案,或者是否有任何包含连接感知表的包。任何建议或替代方案都可以。我有非常复杂的数据集,我正在处理超过 25 个表。我正在寻找解决方案。

【问题讨论】:

  • 你能详细说明为什么有4种组合吗? y3 匹配 y1 但 x1 匹配 x2 背后的逻辑是什么?
  • 这只是我创建的一个虚拟数据,以表明 dt1 依赖于 dt2 和 dt3...所以你可以有 2 个表以 2 种方式加入,因此 4 种方式
  • dt1[dt2] ; dt2[dt1] ; dt1[dt3] ; dt3[dt1] ;
  • 我现在要做的就是探索数据。这是我可以访问的整个数据库快照。我已经将它们导入到多个 csv 中。
  • 你可以查看 dwtools 包,它具有批量连接的功能,在 data.table 包中有一个 FR。您可以将您的用例放在那里,这样我们将确保在实施该功能时不会错过它。

标签: r shiny dplyr data.table


【解决方案1】:

我刚刚发现了一个与同一问题相关的软件包。在这里提一下仅供参考。

https://krlmlr.github.io/dm/articles/dm-visualization.html

它记录本地 r 数据帧的所有连接。一定要看看。

【讨论】:

    【解决方案2】:

    您可以查看将所有查找表绑定在一起。

    dt_dummy = dt1
    dt_lookup = rbindlist(list(dt2, dt3[, .(y2 = y3, x2 = x3)]), idcol = 'ID')
    
    dt_dummy[dt_lookup, on = .(x1 = x2), nomatch = 0L]
    dt_dummy[dt_lookup, on = .(y1 = x2), nomatch = 0L]
    

    如果你必须有一个函数调用,这利用了 R 评估的惰性。它要求您提前提供查找表,但更符合您的问题。请注意,为了减少逻辑语句,此解决方案始终会重新排序您的输入。也就是说,rememberJoin2(dt1, dt2) 的计算结果与 rememberJoin2(dt2, dt1) 相同 - 否则它看起来太乱了。

    dt1_lookup = c('x1', 'y1')
    dtx_lookup = c('x2', 'y3')
    
    rememberJoin2 <- function(t1, t2){
      l = list(substitute(t1), substitute(t2))
    
      #extract the number from dt#
      n <- vapply(l, function(x) as.integer(gsub("dt", "", deparse(x))), 0L)
    
      if(n[1] == n[2]) stop('must provide different data.tables to join')
    
      r <- rank(n)
    
      eval(
        substitute(X[Y, on = .(Xkey == Ykey)],
                   list(X = l[[r[1]]],
                        Y = l[[r[2]]],
                        Xkey = as.name(dt1_lookup[max(n) - 1]), 
                        Ykey = as.name(dtx_lookup[max(n) - 1])
                        )
                   )
        )
    }
    
    rememberJoin2(dt1, dt2)
    rememberJoin2(dt2, dt1)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-05-26
      • 2014-01-25
      • 1970-01-01
      • 1970-01-01
      • 2011-02-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多