让我试着让这个问题尽可能一般。
我们说我有两个变量 a 和 b 。
a <- as.integer(runif(20, min = 0, max = 10))
a <- as.data.frame(a)
b <- as.data.frame(a[c(-7, -11, -15),])
所以 b 有17个观测值,是 a 的子集,有20个观测值。
我的问题如下:我将如何使用这两个变量来生成第三个变量 c ,其中 a 有20个观察值,但观察结果为7,11和缺少15个,其他观察结果与 b 相同但按 a 的顺序?
或者说有点不同:我怎样才能将这些缺失的观察结果插入位置7,11和15的变量 b ?
这看起来非常简单(而且可能是这样)但是我现在已经没有让它工作太久了。
答案 0 :(得分:5)
1)循环试试这个循环:
# test data
set.seed(123) # for reproducibility
a <- as.integer(runif(20, min = 0, max = 10))
a <- as.data.frame(a)
b <- as.data.frame(a[c(-7, -11, -15),])
# lets work with vectors
A <- a[[1]]
B <- b[[1]]
j <- 1
C <- A
for(i in seq_along(A)) if (A[i] == B[j]) j <- j+1 else C[i] <- NA
给出:
> C
[1] 2 7 4 8 9 0 NA 8 5 4 NA 4 6 5 NA 8 2 0 3 9
2)Reduce 这是一个无循环版本:
f <- function(j, a) j + (a == B[j])
r <- Reduce(f, A, acc = TRUE)
ifelse(duplicated(r), NA, A)
,并提供:
[1] 2 7 4 8 9 0 NA 8 5 4 NA 4 6 5 NA 8 2 0 3 9
3)dtw 。在相同名称的包中使用dtw
,我们可以得到一个紧凑的无循环单行:
library(dtw)
ifelse(duplicated(dtw(A, B)$index2), NA, A)
,并提供:
[1] 2 7 4 8 9 0 NA 8 5 4 NA 4 6 5 NA 8 2 0 3 9
已修订已添加其他解决方案。
答案 1 :(得分:3)
这是一种更复杂的方法,使用Levenshtein距离算法,可以更好地处理更复杂的例子(在我尝试的几个较大的测试中它似乎也更快):
# using same data as G. Grothendieck:
set.seed(123) # for reproducibility
a <- as.integer(runif(20, min = 0, max = 10))
a <- as.data.frame(a)
b <- as.data.frame(a[c(-7, -11, -15),])
A = a[[1]]
B = b[[1]]
# compute the transformation between the two, assigning infinite weight to
# insertion and substitution
# using +1 here because the integers fed to intToUtf8 have to be larger than 0
# could also adjust the range more dynamically based on A and B
transf = attr(adist(intToUtf8(A+1), intToUtf8(B+1),
costs = c(Inf,1,Inf), counts = TRUE), 'trafos')
C = A
C[substring(transf, 1:nchar(transf), 1:nchar(transf)) == "D"] <- NA
#[1] 2 7 4 8 9 0 NA 8 5 4 NA 4 6 5 NA 8 2 0 3 9
更复杂的匹配示例(贪婪算法执行效果不佳):
A = c(1,1,2,2,1,1,1,2,2,2)
B = c(1,1,1,2,2,2)
transf = attr(adist(intToUtf8(A), intToUtf8(B),
costs = c(Inf,1,Inf), counts = TRUE), 'trafos')
C = A
C[substring(transf, 1:nchar(transf), 1:nchar(transf)) == "D"] <- NA
#[1] NA NA NA NA 1 1 1 2 2 2
# the greedy algorithm would return this instead:
#[1] 1 1 NA NA 1 NA NA 2 2 2
答案 2 :(得分:2)
数据框版本,与上面的G不完全不同。 (假设a,b设置如上)。
j <- 1
c <- a
for (i in (seq_along(a[,1]))) {
if (a[i,1]==b[j,1]) {
j <- j+1
} else
{
c[i,1] <- NA
}
}