【问题标题】:using data.table to flag the first (or last) record in a group使用 data.table 标记组中的第一条(或最后一条)记录
【发布时间】:2012-05-15 12:15:33
【问题描述】:

给定一个排序键,是否有一个 data.table 快捷方式可以复制 SAS 和 SPSS 中的 firstlast 功能?

下面的行人方法标记了一组的第一个记录。

鉴于 data.table 的优雅(我正在慢慢熟悉它),我假设有一个使用自连接和mult 的快捷方式,但我仍在尝试弄清楚。

示例如下:

require(data.table)

set.seed(123)
n <- 17
DT <- data.table(x=sample(letters[1:3],n,replace=T),
                 y=sample(LETTERS[1:3],n,replace=T))
sortkey  <- c("x","y")
setkeyv(DT,sortkey)
key <- paste(DT$x,DT$y,sep="-")
nw <- c( T , key[2:n]!=key[1:(n-1)] )
DT$first <- 1*nw
DT

【问题讨论】:

  • 这里有很好的答案,包括 data.table 解决方案:stats.stackexchange.com/questions/7884/…
  • 我认为 M.Dimo 特别想标记组中的第一个和最后一个,而不是提取它们。您指向的链接以及 OP 所指的mult 方法显示了如何提取,而不是label

标签: r data.table


【解决方案1】:

这里有几个使用data.table的解决方案:

## Option 1 (cleaner solution, added 2016-11-29)
uDT <- unique(DT)
DT[, c("first","last"):=0L]
DT[uDT, first:=1L, mult="first"]
DT[uDT, last:=1L, mult="last"]


## Option 2 (original answer, retained for posterity)
DT <- cbind(DT, first=0L, last=0L)
DT[DT[unique(DT),,mult="first", which=TRUE], first:=1L]
DT[DT[unique(DT),,mult="last", which=TRUE], last:=1L]

head(DT)
#      x y first last
# [1,] a A     1    1
# [2,] a B     1    1
# [3,] a C     1    0
# [4,] a C     0    1
# [5,] b A     1    1
# [6,] b B     1    1

显然,每一行都包含很多内容。但是,关键构造如下,它返回每个组中第一条记录的行索引:

DT[unique(DT),,mult="first", which=TRUE]
# [1]  1  2  3  5  6  7 11 13 15

【讨论】:

  • 感谢您的回答。我有一种感觉,这可以使用 join & "first" ,但无法找出正确的语法。就在那里,解释得很清楚。再次感谢。
  • 谢谢你们。在实践中,我实际上可能会使用类似@PrasadChalasani 的方法。但我认为这是一个很好的演示 data.table 的一系列功能,并希望其他人会觉得它有用。我也有兴趣了解 (a) 是否有更好的 data.table 解决方案,以及 (b) 是否有比 unique(DT) 更好的方法来提取 data.table 中的所有唯一键组合。
  • @Josh a) 想不出一个,你在 b) 不,unique.data.table 非常快,因为不使用 paste 在引擎盖下,所以想不到有什么更好的。另一种选择是使用list 列来存储每个组的向量结果,而不是一个原子列,它一遍又一遍地重复所有组名。要创建这样的表,请使用j 中的列表列表,例如ans=DT[,list(listcol=list(cumprod(v)),by=x]。结果是每组只有一行。然后每组结果的第一项是:ans[,sapply(listcol,"[",1)].
  • 我也喜欢@Prasad 的方法。 +1。
  • 另一种选择:DT[DT[,.N,by=list(x,y)][,cumsum(N)],last:=1]DT[DT[,.N,by=list(x,y)][,cumsum(N)-N+1],first:=1]
【解决方案2】:

一种简单的方法是使用duplicated() 函数。当应用于数据帧时,当且仅当行值组合之前未发生时,它会生成一个向量,其中条目为 TRUE,当向下移动数据帧时。

DT$first <- !duplicated( DT[, list(x,y) ])                                                                                                                                                                                                                                    
DT$last <- rev(!duplicated( DT[, list(rev(x),rev(y)) ]))                                                                                                                                                                                                                      

> DT                                                                                                                                                                                                                                                                         
       x y first  last                                                                                                                                                                                                                                                        
  [1,] a A  TRUE  TRUE                                                                                                                                                                                                                                                        
  [2,] a B  TRUE  TRUE                                                                                                                                                                                                                                                        
  [3,] a C  TRUE FALSE                                                                                                                                                                                                                                                        
  [4,] a C FALSE  TRUE                                                                                                                                                                                                                                                        
  [5,] b A  TRUE  TRUE                                                                                                                                                                                                                                                        
  [6,] b B  TRUE  TRUE                                                                                                                                                                                                                                                        
  [7,] b C  TRUE FALSE                                                                                                                                                                                                                                                        
  [8,] b C FALSE FALSE                                                                                                                                                                                                                                                        
  [9,] b C FALSE FALSE                                                                                                                                                                                                                                                        
 [10,] b C FALSE  TRUE                                                                                                                                                                                                                                                        
 [11,] c A  TRUE FALSE                                                                                                                                                                                                                                                        
 [12,] c A FALSE  TRUE                                                                                                                                                                                                                                                        
 [13,] c B  TRUE FALSE                                                                                                                                                                                                                                                        
 [14,] c B FALSE  TRUE                                                                                                                                                                                                                                                        
 [15,] c C  TRUE FALSE                                                                                                                                                                                                                                                        
 [16,] c C FALSE FALSE                                                                                                                                                                                                                                                        
 [17,] c C FALSE  TRUE            

另一种不使用duplicated()的方法是:

DT[ unique(DT), list(first = c(1, rep(0,length(y)-1)),                                                                                                                                                                                                                        
                     last =  c(rep(0,length(y)-1),1 )) ]      

      x y  first last                                                                                                                                                                                                                                                   
  [1,] a A     1    1                                                                                                                                                                                                                                                         
  [2,] a B     1    1                                                                                                                                                                                                                                                         
  [3,] a C     1    0                                                                                                                                                                                                                                                         
  [4,] a C     0    1                                                                                                                                                                                                                                                         
  [5,] b A     1    1                                                                                                                                                                                                                                                         
  [6,] b B     1    1                                                                                                                                                                                                                                                         
  [7,] b C     1    0                                                                                                                                                                                                                                                         
  [8,] b C     0    0                                                                                                                                                                                                                                                         
  [9,] b C     0    0                                                                                                                                                                                                                                                         
 [10,] b C     0    1                                                                                                                                                                                                                                                         
 [11,] c A     1    0                                                                                                                                                                                                                                                         
 [12,] c A     0    1                                                                                                                                                                                                                                                         
 [13,] c B     1    0                                                                                                                                                                                                                                                         
 [14,] c B     0    1                                                                                                                                                                                                                                                         
 [15,] c C     1    0                                                                                                                                                                                                                                                         
 [16,] c C     0    0                                                                                                                                                                                                                                                         
 [17,] c C     0    1          

【讨论】:

  • 谢谢!仍然对 data.table 解决方案感到疑惑,但在这种情况下,优雅绝对是合格的。
  • 不客气...我只是添加了另一种方法。您所指的mult 功能仅用于在DT[i,j,mult=... ] 中的i 参数有多个匹配项时选择第一个或最后一个(或所有)匹配项
【解决方案3】:

比 Josh 更简单的方法

unique(DT)
unique(DT,fromLast=TRUE]

【讨论】:

    猜你喜欢
    • 2017-05-08
    • 1970-01-01
    • 2019-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多