我有两个数据框,包含一系列案例。一个从时间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.t1
id ABC Num
1 1 A 101
2 1 B 102
3 1 C 103
4 2 D 104
5 2 E 105
6 3 F 106
7 3 G 107
8 5 H 108
9 5 I 109
10 6 J 110
时间两次滚动
df.t2 <- df.t1
发生了一些变化,
df.t2[3,3] <- 104
df.t2[2,2] <- "H"
df.t2[8,3] <- 999
df.t2[10,3] <- NA
df.t2[11,] <- c(3, "J", 107)
这是时间2,
df.t2
id ABC Num
1 1 A 101
2 1 H 102
3 1 C 104
4 2 D 104
5 2 E 105
6 3 F 106
7 3 G 107
8 5 H 999
9 5 I 109
10 6 J <NA>
11 3 J 107
我现在正在寻找一种快速方法来删除案例,所有id,如果在时间1和时间2之间的情况下(任何行)没有发生任何变化的情况。在具体示例中,它只有id#2在时间1和时间2之间没有发生任何变化。
我正在寻找一个看起来像这样的最终结果,
(df <- subset(df.t2, id != 2))
id ABC Num
1 1 A 101
2 1 H 102
3 1 C 104
6 3 F 106
7 3 G 107
8 5 H 999
9 5 I 109
10 6 J <NA>
11 3 J 107
任何帮助将不胜感激。
答案 0 :(得分:3)
我认为这会奏效。使用data.table
的解决方案:
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
或者,在获得dt = dt1[dt2]
后:
dt2[id %in% dt[, ctr := Num %in% Num.1, by=1:nrow(dt)][ctr == FALSE, unique(id)]]
答案 1 :(得分:3)
使用所有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
这使用dt2和dt1之间的非连接,从这些中选择唯一的id值,然后适当地对dt2
数据进行子集。
关于键中NA值的警告是有问题的......
答案 2 :(得分:2)
试试这个:
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,]
答案 3 :(得分:2)
我真的很喜欢@ alexwhan在这里的答案https://stackoverflow.com/a/14865931/210673,但是由于许多列和长字符串,它听起来很慢。我想知道在数字上为每个组合获得一个唯一的数字会更快。
# 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,]
这里有一个稍微不同的方法来获取us
变量,我希望它有点慢,但需要更加谨慎地将所有内容保持为整数而不是浮点数,因此应该保证唯一性并且我相信任何浮动点溢出会引发警告。 (我也从ms
减去一个,因为它仍然是唯一的,一切都只是小一点。)
base <- as.integer(max(ms)^c(0:(nrow(ms)-1)))
us <- apply((ms-1L) * base, 2, sum)
答案 4 :(得分:1)
好的,这里有一些循环的替代方案。我没有尝试过更复杂的例子,但看看:
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,]