У меня есть решение, использующее data.table
, но оно может быть менее оптимальным для вашего набора данных, учитывая его размер, поскольку он создает дополнительные столбцы.
Хотя в вашем примере данные var1, var2 и var3 всегда были то же самое, я собираюсь предположить здесь, что они не должны быть.
library(data.table)
library(zoo) # for rollapplyr function
df<-setNames(data.frame(matrix(ncol = 4, nrow = 10)), c("code", "var1", "var2", "var3"))
df$code<-c("101", "102", "103", "104", "105", "106", "107", "108", "109", "110")
df$var1<-c(1, 1, 1, 2, 2, 1, 1, 2, 3,3)
df$var2<-c(1, 1,1, 2, 2, 1,1,2, 3,3 )
df$var3<-c(1, 1,1, 2, 2, 1,1,2, 3,3 )
df <- as.data.table(df)
Первым шагом является создание переменной, которая показывает, отличается ли переменная в строке i
от переменной в строке i-1
. Мы делаем это для каждой из трех переменных. Для этого используется функция diff
, которая вычисляет разницу в векторе между i
и i-1
и применяет ее ко всем столбцам.
df[,dif1 := abs(rollapplyr(var1, 2, function(x){diff(x,lag = 1)}, fill = 1)),]
df[,dif2 := abs(rollapplyr(var2, 2, function(x){diff(x,lag = 1)}, fill = 1)),]
df[,dif3 := abs(rollapplyr(var3, 2, function(x){diff(x,lag = 1)}, fill = 1)),]
Если какая-либо из этих переменных изменилась со строки i-1
тогда это не дубликат Поскольку мы взяли абсолютное значение выброса изменения функцией diff
, это означает, что любое значение выше нуля означает изменение. Мы можем взять сумму изменений по трем переменным, а затем отфильтровать те строки, чье изменение больше нуля.
df[,drop := sum(dif1, dif2, dif3), by = code]
df[drop>0, .(code, var1, var2, var3),]
code var1 var2 var3
1: 101 1 1 1
2: 104 2 2 2
3: 106 1 1 1
4: 108 2 2 2
5: 109 3 3 3
Опять же, не уверен, насколько быстро это будет. Я запустил это на 1e4 рядах, и это заняло 0,829 se c, и снова на 1e6 строках, и это заняло 51.118 se c, так что, похоже, все в порядке.