all.different R 中的函数,在循环中应用它?
all.different function in R, apply it in a loop?
我有一个数字向量。例如这样,只有几个唯一值:
set.seed(2)
a = rpois(1000, 0.3)
head(a, 20)
#### [1] 0 0 0 0 1 1 0 1 0 0 0 0 1 0 0 1 2 0 0 0
现在我需要的是找到每个数字,如果本身,前一个和后一个元素都不同。我试图在 R 中找到一个函数 all.different 或所有不同的函数,但没有成功,所以我做到了:
all.diff = function(num) NROW(unique(num))==NROW(num)
然后我想出了一个这样的 for
循环:
ConsecutiveDifferent = function(vector) {
output = numeric(NROW(vector)-2)
for (i in 2:(NROW(vector)-1) ) {
trio <- c(vector[i-1], vector[i], vector[i+1])
if ( all.diff(trio) ) output[i]<-1
}
return(output)
}
res = ConsecutiveDifferent(a)
head(res, 20)
#### [1] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0
它完成了这项工作,但由于我的向量有几亿的长度,我想知道是否有比循环更好的方法来做到这一点。
谢谢,
编辑
谢谢你给我这么多解决方案!我无法决定必须接受谁的答案,所以我做了一个 microbenckmark(长度 = 50000),奖品归 Franck .. 也感谢您的广泛回答。
虽然丑陋,但确实有效。
set.seed(2)
a <- rpois(1000, 0.3)
a_shifted <- embed(a,3)
indices <- 1 + which(apply(X = a_shifted,
FUN = function(num) {length(unique(num))==length(num)},
MARGIN = 1))
print(a[indices])
rle. 这对于三重奏的情况非常特殊:
w = with(rle(a), cumsum(lengths)[
lengths == 1L & c(NA, values[-length(values)]) != c(values[-1], NA)
])
res2 = c(NA, logical(length(a)-2), NA)
res2[w] = TRUE
identical(res, res2) # TRUE
combn.我可能会
a_shift = list(c(NA, a[-length(a)]), a, c(a[-1], NA))
n_distinct = rowSums(combn(a_shift, 2, FUN = function(x) x[[1]] != x[[2]]))
res = n_distinct == length(a_shift)
检查它是否有效...
head(cbind.data.frame(a, res), 20)
a res
1 0 NA
2 0 FALSE
3 0 FALSE
4 0 FALSE
5 1 FALSE
6 1 FALSE
7 0 FALSE
8 1 FALSE
9 0 FALSE
10 0 FALSE
11 0 FALSE
12 0 FALSE
13 1 FALSE
14 0 FALSE
15 0 FALSE
16 1 TRUE
17 2 TRUE
18 0 FALSE
19 0 FALSE
20 0 FALSE
这可以通过扩展 a_shift
扩展到向前和向后看得更远,这可以通过 data.table:
中的 shift
函数轻松完成
library(data.table)
n_back = 1
n_fwd = 1
a_shift = setDT(list(a))[, c(
shift(V1, n_back:0, type="lag"),
list(shift(V1, n_fwd, type="lead"))
)]
a_shift[, r := .I]
resDT = melt(a_shift, id = "r")[, .(res =
if (any(is.na(value))) NA else uniqueN(value) == n_fwd + n_back + 1L
), by=r][, a := a]
identical(res, resDT$res) # TRUE
...这可能看起来很神秘,但这与我的编码风格有关,而不是与程序包有关。
您可以使用duplicated
函数
adjacent_dif <- function(i,l){
as.numeric(!any(duplicated(c(l[i-1], l[i], l[i+1]))))
}
sapply(2:length(a)-1, adjacent_dif, a)
以下步骤不使用迭代器函数(apply like function),我认为它会更快
da = diff(a)
lda = c(0,da)
rda = c(da,0)
sda = lda + rda
res = lda != 0 & rda != 0 & sda != 0
res
首末位置包含FALSE
,与向量a
.
等长
我有一个数字向量。例如这样,只有几个唯一值:
set.seed(2)
a = rpois(1000, 0.3)
head(a, 20)
#### [1] 0 0 0 0 1 1 0 1 0 0 0 0 1 0 0 1 2 0 0 0
现在我需要的是找到每个数字,如果本身,前一个和后一个元素都不同。我试图在 R 中找到一个函数 all.different 或所有不同的函数,但没有成功,所以我做到了:
all.diff = function(num) NROW(unique(num))==NROW(num)
然后我想出了一个这样的 for
循环:
ConsecutiveDifferent = function(vector) {
output = numeric(NROW(vector)-2)
for (i in 2:(NROW(vector)-1) ) {
trio <- c(vector[i-1], vector[i], vector[i+1])
if ( all.diff(trio) ) output[i]<-1
}
return(output)
}
res = ConsecutiveDifferent(a)
head(res, 20)
#### [1] 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0
它完成了这项工作,但由于我的向量有几亿的长度,我想知道是否有比循环更好的方法来做到这一点。
谢谢,
编辑
谢谢你给我这么多解决方案!我无法决定必须接受谁的答案,所以我做了一个 microbenckmark(长度 = 50000),奖品归 Franck .. 也感谢您的广泛回答。
虽然丑陋,但确实有效。
set.seed(2)
a <- rpois(1000, 0.3)
a_shifted <- embed(a,3)
indices <- 1 + which(apply(X = a_shifted,
FUN = function(num) {length(unique(num))==length(num)},
MARGIN = 1))
print(a[indices])
rle. 这对于三重奏的情况非常特殊:
w = with(rle(a), cumsum(lengths)[
lengths == 1L & c(NA, values[-length(values)]) != c(values[-1], NA)
])
res2 = c(NA, logical(length(a)-2), NA)
res2[w] = TRUE
identical(res, res2) # TRUE
combn.我可能会
a_shift = list(c(NA, a[-length(a)]), a, c(a[-1], NA))
n_distinct = rowSums(combn(a_shift, 2, FUN = function(x) x[[1]] != x[[2]]))
res = n_distinct == length(a_shift)
检查它是否有效...
head(cbind.data.frame(a, res), 20)
a res
1 0 NA
2 0 FALSE
3 0 FALSE
4 0 FALSE
5 1 FALSE
6 1 FALSE
7 0 FALSE
8 1 FALSE
9 0 FALSE
10 0 FALSE
11 0 FALSE
12 0 FALSE
13 1 FALSE
14 0 FALSE
15 0 FALSE
16 1 TRUE
17 2 TRUE
18 0 FALSE
19 0 FALSE
20 0 FALSE
这可以通过扩展 a_shift
扩展到向前和向后看得更远,这可以通过 data.table:
shift
函数轻松完成
library(data.table)
n_back = 1
n_fwd = 1
a_shift = setDT(list(a))[, c(
shift(V1, n_back:0, type="lag"),
list(shift(V1, n_fwd, type="lead"))
)]
a_shift[, r := .I]
resDT = melt(a_shift, id = "r")[, .(res =
if (any(is.na(value))) NA else uniqueN(value) == n_fwd + n_back + 1L
), by=r][, a := a]
identical(res, resDT$res) # TRUE
...这可能看起来很神秘,但这与我的编码风格有关,而不是与程序包有关。
您可以使用duplicated
函数
adjacent_dif <- function(i,l){
as.numeric(!any(duplicated(c(l[i-1], l[i], l[i+1]))))
}
sapply(2:length(a)-1, adjacent_dif, a)
以下步骤不使用迭代器函数(apply like function),我认为它会更快
da = diff(a)
lda = c(0,da)
rda = c(da,0)
sda = lda + rda
res = lda != 0 & rda != 0 & sda != 0
res
首末位置包含FALSE
,与向量a
.