数据集中的哪些变量在 id 内是常量

Which variables in dataset are constant within id

我有一个数据集,每个人都有一堆几乎重复的观察结果。我正在尝试准确确定每个特定 ID 的行中哪些变量正在发生变化。

我从检查开始:

dt[ , count := .N, by = id][count > 1, ]

(也使用 headtail),但是有 27000(总)次重复观察——没有办法通过检查来确定哪些变量在变化。

有什么比蛮力方法更好的方法吗? 特别是我希望避免循环,但我看不出如何...

dt[ , count := .N, by = id]
for (var in setdiff(names(dt), c("id", "count"))){
  if (nrow(dt[ , list(.N, count), by = c("id", var)][N < count, ]) > 0){
    print(var)
  }
}

编辑

这里有一个示例数据集来说明:

set.seed(2304)
DT <- data.table(a = rep(sample(5), each = 3),
                 b = sample(15),
                 c = rep(LETTERS[1:5], each = 3),
                 d = rnorm(15),
                 e = rep(6:10, each = 3),
                 f = 15:1,
                 grp = paste0("Group ", rep(1:5, each = 3)))

期望的输出:

c("a", "c", "e")

因为对于 任何 grp 固定值,这些变量都不会改变。

让我们假设 mtcars$carb 是我们的 id。然后,对于每个 id 的每个数字,我们想找出有多少个不同的 gear 值:

data.table(mtcars)[, lapply(.SD, function(x) length(unique(x))), by=carb]

生产

   carb mpg cyl disp hp drat wt qsec vs am gear
1:    4   8   2    8  7    8  9   10  2  2    3
2:    1   7   2    7  6    6  7    7  1  2    2
3:    2   9   2   10  8    9 10   10  2  2    3
4:    3   3   1    1  1    1  3    3  1  1    1
5:    6   1   1    1  1    1  1    1  1  1    1
6:    8   1   1    1  1    1  1    1  1  1    1

任何值 > 1 的变量都有每个 carb 值的变化值。


编辑:

或者,我们可以将其扩展为 运行:

data.table(mtcars)[,lapply(.SD,uniqueN),by=carb
                   ][,!"carb"][,lapply(.SD,table)]

   mpg cyl disp hp drat wt qsec vs am gear
1:   2   3    3  3    3  2    2  4  3    3
2:   1   3    1  1    1  1    1  2  3    1
3:   1   3    1  1    1  1    1  4  3    2
4:   1   3    1  1    1  1    2  2  3    3
5:   1   3    3  3    3  1    2  4  3    1

只有当上述代码的输出是常量且等于 length(unique(id)) 在相应的列中。 carb有6个值,所以可以看出mtcars中的变量nonecarb中是常量。此外,如果我们有很多 ID(在当前示例中有 >50,000),上述方法将很难直接解释。

坚持mtcars,我们可以看到disp中有几个变量是常量:

data.table(mtcars)[,lapply(.SD,uniqueN),by=disp
                   ][,!"disp"][,lapply(.SD,table)]

   mpg cyl hp drat wt qsec vs am gear carb
1:  24  27 26   26 24   23 27 27   27   26
2:   2  27  1    1  2    3 27 27   27    1
3:   1  27 26   26  1    1 27 27   27   26

因此,vsamgeardisp 内是常数。

Michael,仍然不是 100% 清楚您想要的是什么,所以我将提出三种不同的解决方案,从至少有一个具有唯一值的组的所有列开始:

names(
  Filter(
    identity,
    colSums(MT[, lapply(.SD, function(x) uniqueN(x) == .N), by=disp])  
) )[-1]

# [1] "mpg"  "cyl"  "hp"   "drat" "wt"   "qsec" "vs"   "am"   "gear" "carb"

每个组具有唯一值的所有列

names(
  Filter(
    `!`,
    colSums(MT[, lapply(.SD, function(x) uniqueN(x) != .N), by=disp])  
) )

# [1] "qsec"

每组内完全重复的所有变量:

names(
  Filter(
    identity,
    lapply(
      MT[, lapply(.SD, function(x) uniqueN(x) == 1), by=disp][, -1], 
      all
) ) )

# [1] "cyl"  "vs"   "am"   "gear"

请注意,由于组大小 == 1 可以解释为完全唯一或完全重复的特殊情况,所以这三者之间存在重叠。通过修改数据 table 调用中使用的函数,根据您的需要,应该很容易消除歧义。