按顺序匹配向量
Match vectors in sequence
我有 2 个向量。
x=c("a", "b", "c", "d", "a", "b", "c")
y=structure(c(1, 2, 3, 4, 5, 6, 7, 8), .Names = c("a", "e", "b",
"c", "d", "a", "b", "c"))
我想按顺序匹配 a
到 a
,b
到 b
,以便 x[2]
匹配 y[3]
而不是 y[7]
; x[5]
匹配 y[6]
而不是 y[1]
,依此类推。
lapply(x, function(z) grep(z, names(y), fixed=T))
给出:
[[1]]
[1] 1 6
[[2]]
[1] 3 7
[[3]]
[1] 4 8
[[4]]
[1] 5
[[5]]
[1] 1 6
[[6]]
[1] 3 7
[[7]]
[1] 4 8
匹配所有实例。我如何获得这个序列:
1 3 4 5 6 7 8
所以x
中的元素可以相应地映射到y
中的相应值?
可以根据每个元素出现的次数改变names属性然后子集y:
x2 <- paste0(x, ave(x, x, FUN=seq_along))
#[1] "a1" "b1" "c1" "d1" "a2" "b2" "c2"
names(y) <- paste0(names(y), ave(names(y), names(y), FUN=seq_along))
y[x2]
#a1 b1 c1 d1 a2 b2 c2
# 1 3 4 5 6 7 8
嗯,我是用 for-loop 做的
#Initialise the vector with length same as x.
answer <- numeric(length(x))
for (i in seq_along(x)) {
#match the ith element of x with that of names in y.
answer[i] <- match(x[i], names(y))
#Replace the name of the matched element to empty string so next time you
#encounter it you get the next index.
names(y)[i] <- ""
}
answer
#[1] 1 3 4 5 6 7 8
另一种可能性:
l <- lapply(x, grep, x = names(y), fixed = TRUE)
i <- as.integer(ave(x, x, FUN = seq_along))
mapply(`[`, l, i)
给出:
[1] 1 3 4 5 6 7 8
您实际上是在寻找pmatch
pmatch(x,names(y))
[1] 1 3 4 5 6 7 8
与 Ronak 类似的解决方案,但它不会保留对 y 的更改
yFoo<-names(y)
sapply(x,function(u){res<-match(u,yFoo);yFoo[res]<<-"foo";return(res)})
结果
#a b c d a b c
#1 3 4 5 6 7 8
另一个选项使用 Reduce
Reduce(function(v, k) y[-seq_len(v)][k],
x=x[-1L],
init=y[x[1L]],
accumulate=TRUE)
我有 2 个向量。
x=c("a", "b", "c", "d", "a", "b", "c")
y=structure(c(1, 2, 3, 4, 5, 6, 7, 8), .Names = c("a", "e", "b",
"c", "d", "a", "b", "c"))
我想按顺序匹配 a
到 a
,b
到 b
,以便 x[2]
匹配 y[3]
而不是 y[7]
; x[5]
匹配 y[6]
而不是 y[1]
,依此类推。
lapply(x, function(z) grep(z, names(y), fixed=T))
给出:
[[1]]
[1] 1 6
[[2]]
[1] 3 7
[[3]]
[1] 4 8
[[4]]
[1] 5
[[5]]
[1] 1 6
[[6]]
[1] 3 7
[[7]]
[1] 4 8
匹配所有实例。我如何获得这个序列:
1 3 4 5 6 7 8
所以x
中的元素可以相应地映射到y
中的相应值?
可以根据每个元素出现的次数改变names属性然后子集y:
x2 <- paste0(x, ave(x, x, FUN=seq_along))
#[1] "a1" "b1" "c1" "d1" "a2" "b2" "c2"
names(y) <- paste0(names(y), ave(names(y), names(y), FUN=seq_along))
y[x2]
#a1 b1 c1 d1 a2 b2 c2
# 1 3 4 5 6 7 8
嗯,我是用 for-loop 做的
#Initialise the vector with length same as x.
answer <- numeric(length(x))
for (i in seq_along(x)) {
#match the ith element of x with that of names in y.
answer[i] <- match(x[i], names(y))
#Replace the name of the matched element to empty string so next time you
#encounter it you get the next index.
names(y)[i] <- ""
}
answer
#[1] 1 3 4 5 6 7 8
另一种可能性:
l <- lapply(x, grep, x = names(y), fixed = TRUE)
i <- as.integer(ave(x, x, FUN = seq_along))
mapply(`[`, l, i)
给出:
[1] 1 3 4 5 6 7 8
您实际上是在寻找pmatch
pmatch(x,names(y))
[1] 1 3 4 5 6 7 8
与 Ronak 类似的解决方案,但它不会保留对 y 的更改
yFoo<-names(y)
sapply(x,function(u){res<-match(u,yFoo);yFoo[res]<<-"foo";return(res)})
结果
#a b c d a b c
#1 3 4 5 6 7 8
另一个选项使用 Reduce
Reduce(function(v, k) y[-seq_len(v)][k],
x=x[-1L],
init=y[x[1L]],
accumulate=TRUE)