R中使用Data.Table的两个列表的逐行差异

时间:2018-10-28 19:21:47

标签: r data.table

我想使用data.table增量地查找新元素,即对于每一行,我都会查看列表中的值是否以前已经被查看过。如果它们是,我们将忽略它们。如果没有,我们将选择它们。

我能够按组将元素包装在列表中,但是我不确定如何找到增量差异。

这是我的尝试:

       df = data.table::data.table(id = c('A','B','C','A','B','A','A','A','D','E','E','E'), 
Value = c(1,2,3,4,3,5,2,3,7,2,3,9))

       df_wrapped=df[,.(Values=(list(unique(Value)))), by=id]

       expected_output = data.table::data.table(id = c("A","B","C","D","E"),
Value = list(c(1,4,5,2,3),c(2,3),c(3),c(7),c(2,3,9)),
Diff=list(c(1,4,5,2,3),c(NA),c(NA),c(7),c(9)),
Count = c(5,0,0,1,1))

关于预期输出的想法:

  • 对于第一行,所有元素都是唯一的。因此,我们将它们包含在Diff列中。
  • 在第二行中,2,3已出现在第1行中。因此,我们将忽略它们。第3行同上。
  • 类似地,在第4行和第5行中首次出现79,因此我们将它们包括在内。

这里是视觉表示:

expected_output
   id     Value      Diff Count
    A 1,4,5,2,3 1,4,5,2,3     5
    B       2,3        NA     0
    C         3        NA     0
    D         7         7     1
    E     2,3,9         9     1

我将不胜感激。由于原始数据集中的性能问题,我只在寻找基于data.table的解决方案。

2 个答案:

答案 0 :(得分:2)

我不确定您为什么特别需要将它们放在列表中,否则我写了一小段可以为您提供帮助的东西。

df = data.table::data.table(id = c('A','B','C','A','B','A','A','A','D','E','E','E'), 
                            Value = c(1,2,3,4,3,5,2,3,7,2,3,9))

df = df[order(id, Value)]
df = df[duplicated(Value) == FALSE, diff := Value][]
df = df[, count := uniqueN(diff, na.rm = TRUE), by = id]

结果将是:

> df
    id Value diff count
 1:  A     1    1     5
 2:  A     2    2     5
 3:  A     3    3     5
 4:  A     4    4     5
 5:  A     5    5     5
 6:  B     2   NA     0
 7:  B     3   NA     0
 8:  C     3   NA     0
 9:  D     7    7     1
10:  E     2   NA     1
11:  E     3   NA     1
12:  E     9    9     1

希望这会有所帮助,或者至少会让您入门。

答案 1 :(得分:1)

这是另一种可能的方法:

library(data.table)
df = data.table(
    id = c('A','B','C','A','B','A','A','A','D','E','E','E'), 
    Value = c(1,2,3,4,3,5,2,3,7,2,3,9))

valset <- c()
df[, {
        d <- setdiff(Value, valset)
        valset <- unique(c(valset, Value))
        .(Values=.(Value), Diff=.(d), Count=length(d))
    }, 
    by=.(id)]

输出:

   id    Values      Diff Count
1:  A 1,4,5,2,3 1,4,5,2,3     5
2:  B       2,3               0
3:  C         3               0
4:  D         7         7     1
5:  E     2,3,9         9     1