如何使用data.table和sqldf得到相同的分组结果?

goqiplq2  于 2021-07-26  发布在  Java
关注(0)|答案(2)|浏览(303)

我尝试使用sqldf和data.table实现sql查询。
我需要分别使用这两个不同的库来完成。
不幸的是,我不能使用data.table产生相同的结果。

  1. library(sqldf)
  2. library(data.table)
  3. Id <- c(1,2,3,4)
  4. HasPet <- c(0,0,1,1)
  5. Age <- c(20,1,14,10)
  6. Posts <- data.table(Id, HasPet, Age)
  7. # sqldf way
  8. ref <- sqldf("
  9. SELECT Id, HasPet, MAX(Age) AS MaxAge
  10. FROM Posts
  11. GROUP BY HasPet
  12. ")
  13. # data.table way
  14. res <- Posts[,
  15. list(Id, HasPet, MaxAge=max(Age)),
  16. by=list(HasPet)]
  17. head(ref)
  18. head(res)

sqldf的输出为:

  1. > head(ref)
  2. Id HasPet MaxAge
  3. 1 1 0 20
  4. 2 3 1 14

虽然data.table的输出不同:

  1. > head(res)
  2. HasPet Id HasPet MaxAge
  3. 1: 0 1 0 20
  4. 2: 0 2 0 20
  5. 3: 1 3 1 14
  6. 4: 1 4 1 14

请注意,sql查询不能修改。

mefy6pfw

mefy6pfw1#

这就产生了大量的data.table。如果要按组计算最大值或最小值,最好的方法是自联接。很快,只是有点神秘。
您可以一步一步地建立它:在data.table中,您可以在i中选择,在j中执行,然后分组。因此,第一步是在团队的每个层次中找到我们想要的东西

  1. Posts[, Age == max(Age), by = HasPet]
  2. # HasPet V1
  3. # 1: 0 TRUE
  4. # 2: 0 FALSE
  5. # 3: 1 TRUE
  6. # 4: 1 FALSE

我们可以用 .I 要检索每行的整数向量,那么之前的v1逻辑向量true和false在每个组中都有索引,所以我们只有包含每个组的max的行。

  1. Posts[, .I[Age == max(Age)], by=HasPet]
  2. # From the data.table special symbols help:
  3. # .I is an integer vector equal to seq_len(nrow(x)). While grouping,
  4. # it holds for each item in the group, its row location in x. This is useful
  5. # to subset in j; e.g. DT[, .I[which.max(somecol)], by=grp].
  6. # HasPet V1
  7. # 1: 0 1
  8. # 2: 1 3

然后我们使用刚才生成的v1列来调用data.table中的特定行(1和3)。就这样!

  1. Posts[Posts[, .I[Age == max(Age)], by=HasPet]$V1]
展开查看全部
mu0hgdu0

mu0hgdu02#

你可以用 .SD 为的每个值获取行的子集 HasPet .

  1. library(data.table)
  2. Posts[, .SD[Age==max(Age)], HasPet]
  3. # HasPet Id Age
  4. # 1: 0 1 20
  5. # 2: 1 3 14

相关问题