R 移除案例,所有id';s、 对于在时间1和时间2之间未发生任何更改的情况

R 移除案例,所有id';s、 对于在时间1和时间2之间未发生任何更改的情况,r,data-management,R,Data Management,我有两个数据帧和一系列的案例。一个来自时间1,一个来自时间2。我正在寻找一种方法来快速识别在时间1和时间2之间发生变化的情况,我有点卡住了 这里有一个例子。我有一个时间1的数据帧 df.t1 <- data.frame(id = c(1,1,1,2,2,3,3,5,5,6), ABC = LETTERS[1:10], Num = 101:110) 时间一转二 df.t2 <- df.t1 df.t2试试这个: df.t1$interact <- with(df.t1, in

我有两个数据帧和一系列的案例。一个来自时间1,一个来自时间2。我正在寻找一种方法来快速识别在时间1和时间2之间发生变化的情况,我有点卡住了

这里有一个例子。我有一个时间1的数据帧

df.t1 <- data.frame(id = c(1,1,1,2,2,3,3,5,5,6), ABC = LETTERS[1:10], Num = 101:110)
时间一转二

df.t2 <- df.t1
df.t2试试这个:

df.t1$interact <- with(df.t1, interaction(id, ABC, Num))
df.t2$interact <- with(df.t2, interaction(id, ABC, Num))

change.ids <- unique(df.t2$id[!df.t2$interact %in% df.t1$interact])
new.df <- df.t2[df.t2$id %in% change.ids,]

df.t1$interact我认为这会奏效。使用
数据的解决方案。表

require(data.table)
dt1 <- data.table(df.t1)
dt2 <- data.table(df.t2)
# your conversion made them characters
dt2[, `:=`(id = as.numeric(id), Num = as.numeric(Num))]
setkey(dt1, "id", "ABC")
setkey(dt2, "id", "ABC")
dt <- dt1[dt2]
dt2[id %in% dt[, !(all(Num == Num.1)) | any(is.na(c(Num, Num.1))), by=id][V1 == TRUE]$id]

#    id ABC Num
# 1:  1   A 101
# 2:  1   C 104
# 3:  1   H 102
# 4:  3   F 106
# 5:  3   G 107
# 6:  3   J 107
# 7:  5   H 999
# 8:  5   I 109
# 9:  6   J  NA

使用data.table和按所有
id
ABC
NUM

require(data.table)
dt1 <- data.table(df.t1)
dt2 <- data.table(df.t2)
# your conversion made them characters
dt2[, `:=`(id = as.numeric(id), Num = as.numeric(Num))]
setkey(dt1, "id", "ABC", "Num")
setkey(dt2, "id", "ABC", "Num")
# then it is just

dt2[dt2[!dt1][,list(unique(id))]]


   id ABC Num
1:  1   A 101
2:  1   C 104
3:  1   H 102
4:  3   F 106
5:  3   G 107
6:  3   J 107
7:  5   H 999
8:  5   I 109
9:  6   J  NA
require(data.table)

dt1好的,这里有一个循环的替代方案。我没有在更复杂的示例中尝试过,但请看一下:

no.change <- vector()
#identifies rows which don't change
for(i in 1:nrow(df.t2)) { 
    for(k in 1:nrow(df.t1)) {
    if(all(df.t2[i,]==df.t1[k,],na.rm=TRUE)) #na.rm gets rid of error
   no.change <- c(no.change, i)
  }
}
# gets ids from all the other rows
id.change <- df.t2$id[-no.change]
df <- df.t2[df.t2$id %in% id.change,]

no.change我真的很喜欢@alexwhan的答案,但由于有很多列和长字符串,听起来组合起来很慢。我想知道在数字上为每个组合获得唯一的数字是否会更快

# get a matrix of unique integers for each column (stacking the two data frames)
ms <- do.call(cbind, lapply(seq_len(ncol(df.t1)), function(ni) {
  xi <- c(as.character(df.t1[[ni]]), as.character(df.t2[[ni]]))
  match(xi, unique(xi))
}))
# convert to base max(ms) to get a single unique identifying number
us <- as.vector(ms %*% max(ms)^c(0:(ncol(ms)-1)))
u2 <- us[(nrow(df.t1)+1):length(us)]
u1 <- us[1:nrow(df.t1)]
# now get changed values and proceed as in alexwhan's answer
ch <- unique(df.t2$id[! u2 %in% u1])
df.t2[df.t2$id %in% ch,]


id=3
有一个更改(一个新条目)。“你不考虑他们?”Arun,我的坏人。我颠倒了观点,我将更新问题。谢谢为了增加一些额外的澄清,我想在
df
中保留在时间1和时间2之间发生变化的案例。如果还不清楚,请告诉我!谢谢你回答我的问题。它似乎在您的更新后工作,唯一的问题是我必须在
interaction()
中定义
id
ABC
Num
,但我想我可以使用
names()
。您希望发生什么?您的数据结构如何?您确实解决了这个问题,问题是在实际数据中,我有34列,其中一些列中有一些文本,因此将它们粘贴到I
interact
可能不是最佳解决方案。你能想出一种方法让我逐行比较它吗?如果它是手动命名你担心的列,这可能会起作用:
df.t1$interact我喜欢`交互((df.t1[,1:ncol(df.t1)])。它可能很难看,但它使它更灵活。谢谢!我从来没有独自想到过。同样,问题是实际数据有很多列,似乎我必须在这个函数中命名它们。不管怎样,您回答了我的问题。因此,您希望更改为从
df.t2
中选择“任意”列吗??如果是这样的话,我会在当天晚些时候编辑这篇文章。我要找的是在时间1和时间2之间更改的任何一行,如果一行更改了,我想要与该id相关的所有行。我试图在问题的最后部分说明这一点。是的,但这是一个合并。他需要的是两者不相等的东西。举个例子:你得到了这里
id=2
,这不应该在那里。好的一点@Arun,我已经重新考虑过了,编辑过了。我不能让
NA
引起问题,但在某些情况下它可能会。(+1)太棒了!我与dt2[!dt1]非常接近,但请不要想这个!!我确信在数据表中必须有一个等价的
setdiff
(对于向量)。@mnel,这是否意味着我需要在我的真实数据中将所有34个列名设置为
setkey
?是的,您可以执行
setkeyv(DT,names(DT))
以避免将它们全部拼写出来(并确保id是列号1)谢谢你再次尝试!它在if(all(df.t2[i,]==df.t1[k,])中得到这个错误
error。没有。这个更改属于。永远不要以那种方式生长对象!我知道我知道(你应该看到一些真正丑陋的东西)-太多时候“它现在就起作用”会让人觉得grade@alexwhan,但是……嗯。我不知道我对用返回错误的代码来解决某些问题有什么感觉。无论如何,你是对的。这个解决方案是第一个真正适用于我的数据的解决方案。非常感谢您找到了这个解决方案。我还没有完全理解它,但我很感激它就在那里。谢谢特别是对于R,一个好的解决方案取决于数据集的大小,因此,尽管总是推荐使用一个小的可重复示例,但它也确实有助于说明数据集的大小;在这种情况下,不仅要知道有多少行和列,还要知道每列中有多少ID和多少唯一的内容。(最后一个问题可能会影响我的解决方案;我有点担心整数溢出。)感谢您提供了一些非常合理的建议。我将在今天晚些时候(以及将来的问题中)将这些信息添加到我的帖子中。你有什么好的资料可以让我了解更多关于整数溢出的信息吗?顺便问一下,@alexwhan的答案是不是用
paste
而不是
interactive
?如果这样做有效的话,这种复杂的情况是不必要的。。。
require(data.table)
dt1 <- data.table(df.t1)
dt2 <- data.table(df.t2)
# your conversion made them characters
dt2[, `:=`(id = as.numeric(id), Num = as.numeric(Num))]
setkey(dt1, "id", "ABC")
setkey(dt2, "id", "ABC")
dt <- dt1[dt2]
dt2[id %in% dt[, !(all(Num == Num.1)) | any(is.na(c(Num, Num.1))), by=id][V1 == TRUE]$id]

#    id ABC Num
# 1:  1   A 101
# 2:  1   C 104
# 3:  1   H 102
# 4:  3   F 106
# 5:  3   G 107
# 6:  3   J 107
# 7:  5   H 999
# 8:  5   I 109
# 9:  6   J  NA
dt2[id %in% dt[, ctr := Num %in% Num.1, by=1:nrow(dt)][ctr == FALSE, unique(id)]]
require(data.table)
dt1 <- data.table(df.t1)
dt2 <- data.table(df.t2)
# your conversion made them characters
dt2[, `:=`(id = as.numeric(id), Num = as.numeric(Num))]
setkey(dt1, "id", "ABC", "Num")
setkey(dt2, "id", "ABC", "Num")
# then it is just

dt2[dt2[!dt1][,list(unique(id))]]


   id ABC Num
1:  1   A 101
2:  1   C 104
3:  1   H 102
4:  3   F 106
5:  3   G 107
6:  3   J 107
7:  5   H 999
8:  5   I 109
9:  6   J  NA
no.change <- vector()
#identifies rows which don't change
for(i in 1:nrow(df.t2)) { 
    for(k in 1:nrow(df.t1)) {
    if(all(df.t2[i,]==df.t1[k,],na.rm=TRUE)) #na.rm gets rid of error
   no.change <- c(no.change, i)
  }
}
# gets ids from all the other rows
id.change <- df.t2$id[-no.change]
df <- df.t2[df.t2$id %in% id.change,]
# get a matrix of unique integers for each column (stacking the two data frames)
ms <- do.call(cbind, lapply(seq_len(ncol(df.t1)), function(ni) {
  xi <- c(as.character(df.t1[[ni]]), as.character(df.t2[[ni]]))
  match(xi, unique(xi))
}))
# convert to base max(ms) to get a single unique identifying number
us <- as.vector(ms %*% max(ms)^c(0:(ncol(ms)-1)))
u2 <- us[(nrow(df.t1)+1):length(us)]
u1 <- us[1:nrow(df.t1)]
# now get changed values and proceed as in alexwhan's answer
ch <- unique(df.t2$id[! u2 %in% u1])
df.t2[df.t2$id %in% ch,]
base <- as.integer(max(ms)^c(0:(nrow(ms)-1)))
us <- apply((ms-1L) * base, 2, sum)