确定数据框中的列何时更改值,并返回更改的索引。

13

我正在尝试找到一种方法来确定数据框中一组列何时更改其值。让我直接说明,请考虑以下示例:

x<-data.frame(cnt=1:10, code=rep('ELEMENT 1',10), val0=rep(5,10), val1=rep(6,10),val2=rep(3,10))
x[4,]$val0=6
  • cnt列是唯一的ID(可以是日期或时间列,在此简化为int)。
  • code列类似于一组行的代码(想象几个具有不同代码的这样的组)。代码和计数是我的数据表中的键。
  • val0、val1、val2列类似于分数。

上面的数据框应该被理解为:'ELEMENT 1'的分数从5、6、3开始,保持不变,直到第4次迭代时它们变成了6、6、3,然后又变回了5、6、3。

我的问题是,有没有办法获取数据框的第1、第4和第5行?有没有办法检测列何时发生更改?(此处有12列)

我尝试使用data.table的重复函数(在大多数情况下完美地工作),但在这种情况下,它将删除所有重复项,并仅留下第1和第4行(删除第5行)。

你有什么建议吗?我不想使用for循环,因为大约有200万行。


cnt列是唯一的ID(可以是日期或时间列,在此简化为int)。 code列类似于一组行的代码(想象几个具有不同代码的这样的组)。代码和计数是我的data.table中的键。 val0、val1、val2列类似于分数。 上面的数据框应该被理解为:'ELEMENT 1'的分数从5、6、3开始,保持不变,直到第4次迭代时它们变成了6、6、3,然后又变回了5、6、3。 我的问题是,有没有办法获取数据框的第1、第4和第5行?有没有办法检测列何时发生更改?(此处有12列) 我尝试使用data.table的重复函数(在大多数情况下完美地工作),但在这种情况下,它将删除所有重复项,并仅留下第1和第4行(删除第5行)。 你有什么建议吗?我不想使用for循环,因为大约有200万行。
2个回答

18
在CRAN的稳定版本中,data.table 1.8.10中有一个名为duplist的(未导出的)函数可以完全实现这一点。它还是用C编写的,因此速度非常快。
require(data.table) # 1.8.10
data.table:::duplist(x[, 3:5]) 
# [1] 1 4 5

如果您正在使用 data.table 的开发版本(1.8.11),那么有一个更高效(在内存方面)的版本被重命名为 uniqlist,执行完全相同的工作。也许这应该在下一版中发布。好像在 Stack Overflow 上出现过多次。让我们看看。

require(data.table) # 1.8.11
data.table:::uniqlist(x[, 3:5])
# [1] 1 4 5

2
嗨,阿伦,你太棒了。老实说,我几乎完全使用data.table。如果您不介意,我有一个额外的问题。当我运行data.frame :: duplist时,我会收到一个错误[...]不是列表类型。参数不应该是data.table吗?只是为了澄清,这正是我正在寻找的功能。一旦您对我的问题发表评论,我将接受此答案。谢谢。 - Nikos
3
Nikos,uniqlist/duplistdata.table 包中的一个函数。由于该函数未被导出,因此您需要使用 data.table::: 运算符才能访问它。它基本上将在数据框/数据表上运行(因为它期望列表输入)。希望这能澄清问题? - Arun
1
当然。这基本上会为您提供每个唯一组合的索引。更像rle,但适用于列表,但返回的是索引而不是值。 - Arun
2
我刚刚意识到你是一个 data.table 的开发者 -- 难怪!问题已提交 - Heisenberg
@Arun,这个稳定性有多高?我想把使用data.table:::uniqlist的东西放到生产代码中,但我知道这是不被赞同的,因为我当然不是data.table的开发人员,因此该方法可能会改变。(请参见此处的不满:https://stat.ethz.ch/pipermail/r-devel/2013-August/thread.html#67180) - ijoseph
显示剩余5条评论

3
完全看不懂,但是:
c(1,which(rowSums(sapply(x[,grep('val',names(x))],diff))!=0)+1)
# [1] 1 4 5

基本上,对每一行运行diff,找出所有的变化。如果任何列发生了变化,则该行发生了变化。

此外,没有使用sapply

c(1,which(rowSums(diff(as.matrix(x[,grep('val',names(x))])))!=0)+1)

1
+1,注意给楼主的是你需要使用上述表达式对数据框进行子集化(可能很明显,但以防万一...)。 - BrodieG
没有问题,谢谢。它的运行非常完美。但是当在200万行上运行时速度有点慢。我担心我会依赖Arun的答案(出于许多原因)。感谢您的时间。 - Nikos

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接