为我提供了一个大数据表,其中包含两个指标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
。在上面的示例中,构造就是这种情况。
答案 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