【问题标题】:flag groups with identical rows in some columns of a data.table在 data.table 的某些列中标记具有相同行的组
【发布时间】:2020-06-19 16:50:15
【问题描述】:

我有一个大型数据表,其结构与这个可重现的示例相似:

d <- data.table(
  g     =c(1  ,1  ,2  ,2  ,2  ,3  ,3  , 4 , 4),
  A     =c('a','a','b','b','w','c','q','r','r'),
  B     =c(1  ,1  ,2  ,2  ,2  ,3  ,3  ,4  , 5),
  sameA =c(T  , T , F , F , F , F , F , T , T),
  sameAB=c(T  , T , F , F , F , F , F , F , F)
 )

g 表示组,AB 是个人特征。我想创建变量:

  • sameA :表示 A 对于组的所有观察值都是相同的
  • sameAB :表示 A 和 B 对于组的所有观察值都相同

如何使用 data.table 以有效的方式做到这一点?

【问题讨论】:

标签: r data.table


【解决方案1】:

也许你可以试试这个。使用uniqueN 确定每组唯一值的数量(使用by = g),并与1 进行比较。

library(data.table)

d[, c("sameAnew", "saveABnew") := list(uniqueN(A) == 1, uniqueN(A) == 1 & uniqueN(B) == 1), by = g]

或者按照@jangorecki 的建议,创建一个用大括号{} 抑制的临时变量,以避免重复uniqueN(A)

d[, c("sameAnew", "saveABnew") := {tmp <- uniqueN(A); list(tmp == 1, tmp == 1 & uniqueN(B) == 1)}, by = g]

输出

   g A B sameA sameAB sameAnew saveABnew
1: 1 a 1  TRUE   TRUE     TRUE      TRUE
2: 1 a 1  TRUE   TRUE     TRUE      TRUE
3: 2 b 2 FALSE  FALSE    FALSE     FALSE
4: 2 b 2 FALSE  FALSE    FALSE     FALSE
5: 2 w 2 FALSE  FALSE    FALSE     FALSE
6: 3 c 3 FALSE  FALSE    FALSE     FALSE
7: 3 q 3 FALSE  FALSE    FALSE     FALSE
8: 4 r 4  TRUE  FALSE     TRUE     FALSE
9: 4 r 5  TRUE  FALSE     TRUE     FALSE

【讨论】:

  • 你可以避免j = {tmp&lt;-uniqueN(A); your_j_arg}两次调用uniqueN(A)
  • @Ben,TK。这似乎工作正常,但速度很慢。我对 1pct 的数据样本进行了测试,但仍然需要很长时间来计算这些数据。
  • @LucasMation 我明白了。肯定会看看@chinsoon12 的答案。如果uniqueN 导致缓慢(请参阅github issue),您可以尝试@chinsoon12 描述的length(unique())duplicated()。请随意描述您的数据集(总体大小,也许是组的平均大小)...
  • 数据集大约有 500m 个观测值,100m 个组,每组 10 个观测值。我稍后会测试你的建议和下面的建议。从issue中我们可以看出uniqueN表现不佳的情况。
【解决方案2】:

您对您希望发生的事情的解释不够准确,我无法知道我是否会给您您正在寻找的答案。

我的解释是,“我想要一个只有唯一行的数据表”

如果是这样,那么以下应该可以工作。

d <- as.data.frame(d)
d <- data.table::data.table(unique.data.frame(d))

【讨论】:

    【解决方案3】:

    这是另一种选择:

    isdup <- function(x) duplicated(x) | duplicated(x, fromLast=TRUE)
    
    d[, adup := isdup(.SD), .SDcols=c("g", "A")][,
        sameA2 := !any(!adup), g]
    
    d[, sameAB2 := FALSE][
        (sameA2), bdup := isdup(.SD), .SDcols=c("g", "B")][
            (sameA2), sameAB2 := !any(!bdup), g]
    

    还有一个非正统的不by 版本:

    d[order(g, A, B), c("sameA3", "sameAB3") := {
        a <- rleid(g, A)
        b <- rleid(g, B)
        newg <- which(diff(g) > 0L)
    
        nas <- rep(NA_integer_, .N)
        acnt <- a - nafill(nafill(replace(nas, newg + 1L, a[newg]), "locf"), fill=0L)
        bcnt <- b - nafill(nafill(replace(nas, newg + 1L, b[newg]), "locf"), fill=0L)
    
        acnt[-c(newg, .N)] <- NA_integer_
        acnt <- nafill(acnt, "nocb")
        bcnt[-c(newg, .N)] <- NA_integer_
        bcnt <- nafill(bcnt, "nocb")
    
        l <- acnt == 1L
        .(l, l & bcnt == 1L)
    }]
    

    您介意在您的大型数据集上分享时间吗?

    【讨论】:

      猜你喜欢
      • 2017-09-12
      • 2016-11-05
      • 2021-04-12
      • 2014-09-21
      • 1970-01-01
      • 2016-07-13
      • 1970-01-01
      • 1970-01-01
      • 2022-11-28
      相关资源
      最近更新 更多