检查两个指标是否相同

时间:2019-07-16 15:34:57

标签: r data.table grouping indicator

为我提供了一个大数据表,其中包含两个指标Calhoun 0.3 Bureau 0.8 Carroll 1.1 Boone 2.6 Adams 3.7 Cass 4.4 Bond 6.5 Champaign 12.8 Brown 19.1 Alexander 36.1 ind1,并且可能重复。例如

ind2

我现在要检查这两个指标是否以相同的方式对数据进行分组,即

当且仅当两行也都具有相同的指示符 set.seed(1) ind1 <- sample(1:3,1000, replace=TRUE ) ind2 <- c("a","b","c")[ind1] dt <- data.table(ind1=ind1, ind2=ind2) 时,两行才具有相同的指示符ind1。在上面的示例中,构造就是这种情况。

3 个答案:

答案 0 :(得分:3)

您可以简单地按ind2分组并计算不同的ind1,反之亦然。如果任何计数> 1,那么它们将不会以相同的方式对数据进行分组。这是使用基数R的方法-

any(with(dt, ave(ind1, ind2, FUN = function(x) length(unique(x)))) > 1)

[1] FALSE # means ind1 and ind2 group the data in same way

或者,您可以使用all检查是否所有计数== 1,是否更容易解释-

all(with(dt, ave(ind1, ind2, FUN = function(x) length(unique(x)))) == 1)

[1] TRUE # means ind1 and ind2 group the data in same way

答案 1 :(得分:3)

我的直觉是像@IceCreamToucan的答案一样使用.GRP,但另一种方法是联合删除两列的重复项,然后分别检查每列中的重复项:

# data.table
unique(dt[, c("ind1", "ind2")])[, !(anyDuplicated(ind1) || anyDuplicated(ind2))]

# base, with df = data.frame(dt)
with(unique(df[, c("ind1", "ind2")]), !(anyDuplicated(ind1) || anyDuplicated(ind2)))

我尝试了各种基准测试,但没有看到任何明确的结果,只是令人惊讶的是,上述两种选择之间的时机几乎总是非常有利于data.table。

带有#rows和#groups参数的示例:

library(data.table)
library(magrittr)

ng = 150
n = 1e6
set.seed(1)
ind1 <- sample(1:ng, n, replace=TRUE )
ind2 <- -ind1

dt <- data.table(ind1=ind1, ind2=ind2)
df = data.frame(dt)

microbenchmark::microbenchmark(times = 3L,
grp = dt[,  g1 := .GRP, ind1][, g2 := .GRP, ind2][, all(g1 == g2)], 
uniques = dt[, uniqueN(ind2), ind1][, all(V1 == 1)],
shreet = with(dt, max(tapply(ind1, ind2, function(x) length(unique(x))))) == 1L,
shreep = with(dt, tapply(ind1, ind2, . %>% unique %>% length)) %>% max %>% equals(1L),
another = unique(dt[, c("ind1", "ind2")])[, !(anyDuplicated(ind1) || anyDuplicated(ind2))],
banother = with(unique(df[, c("ind1", "ind2")]), !(anyDuplicated(ind1) || anyDuplicated(ind2)))
)

结果:

Unit: milliseconds
     expr        min         lq       mean     median         uq        max neval
      grp   31.89250   34.92348   46.06510   37.95446   53.15140   68.34833     3
  uniques   32.82520   34.36808   36.32377   35.91097   38.07306   40.23515     3
   shreet   38.26046   38.35256   44.37116   38.44467   47.42650   56.40834     3
   shreep   43.37336   98.56367  145.38600  153.75399  196.39231  239.03064     3
  another   14.47064   31.42879   88.20134   48.38694  125.06669  201.74643     3
 banother 1338.14070 1427.35481 1658.08404 1516.56893 1818.05572 2119.54251     3

答案 2 :(得分:2)

您可以使用两个变量创建一个数字组索引,并检查所有行的索引是否相等。

这会将两个组索引添加到表中并检查是否相等,但是如果需要,您可以在之后删除列

dt[,  g1 := .GRP, ind1][, g2 := .GRP, ind2][, all(g1 == g2)]
#[1] TRUE

编辑:Shree独特的计数方法更好。有关data.table的实现,请参见下文

Edit2:另请参阅其他解决方案的评论

dt[, uniqueN(ind2), ind1][, all(V1 == 1)]
#[1] TRUE

具有1e7行和10组表的基准,用两个相等的列表示

set.seed(1)
ind1 <- sample(1:10,1e7, replace=TRUE )
ind2 <- c("a","b","c")[ind1]

dt <- data.table(ind1=ind1, ind2=ind2)

microbenchmark::microbenchmark(
grp = dt[,  g1 := .GRP, ind1][, g2 := .GRP, ind2][, all(g1 == g2)], 
uniques = dt[, uniqueN(ind2), ind1][, all(V1 == 1)]
)

# Unit: milliseconds
#     expr      min       lq    mean   median       uq       max neval cld
#      grp 727.9489 838.2190 918.280 879.1036 971.3982 1542.9655   100   b
#  uniques 472.1311 502.1327 529.581 526.5357 540.5406  723.5078   100  a