确定data.frame的列何时更改值并返回更改的索引

时间:2014-01-21 18:15:20

标签: r duplicates dataframe data.table

我正在尝试找到一种方法来确定一组列何时更改data.frame中的值。让我直截了当,请考虑以下示例:

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)
  • 代码列就像行集的代码(想象几个这样的组,但代码不同)。代码和cnt是我的data.table中的键。
  • val0,val1,val2列类似于得分。

上面的data.frame应该被理解为:'ELEMENT 1'的分数从5,6,3开始,一直保持到4迭代时它们变为6,6,3,然后又变回5,6,3。

我的问题是,有没有办法获得data.frame的第1,第4和第5 行?有没有办法检测列何时发生变化? (btw有12列)

我尝试使用data.table的重复(在大多数情况下都能很好地工作)但在这种情况下它会删除所有重复项并仅保留第1行和第4行(删除第5行) )。

你有什么建议吗?我宁愿不使用for循环,因为有大约。 2M行。

2 个答案:

答案 0 :(得分:12)

data.table版本1.8.10(CRAN中的稳定版本)中,有一个名为duplist的(n)(未导出)函数正是这样做的。它也是用C语言编写的,因此非常快。

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

如果您使用的是data.table(1.8.11)的开发版本,则会有一个更高效的版本(就内存而言)重命名为uniqlist,它完成相同的工作。可能这应该导出到下一个版本。似乎不止一次出现过SO。我们来看看。

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

答案 1 :(得分: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)