向量中不同元素之间的元素数计数
Count of number of elements between distinct elements in vector
假设我有一个值向量,例如:
A C A B A C C B B C C A A A B B B B C A
我想为每个元素创建一个新向量,其中包含自上次看到该元素以来的元素数。所以,对于上面的向量,
NA NA 2 NA 2 4 1 4 1 3 1 7 1 1 6 1 1 1 8 6
(其中 NA
表示这是第一次看到该元素)。
比如第一个A和第二个A分别在1号位和3号位,相差2;第三个和第四个A在位置4和11,相差7,依此类推。
是否有预建的管道兼容函数可以执行此操作?
我把这个函数拼凑在一起来演示:
# For reproducibility
set.seed(1)
# Example vector
x = sample(LETTERS[1:3], size = 20, replace = TRUE)
compute_lag_counts = function(x, first_time = NA){
# return vector to fill
lag_counts = rep(-1, length(x))
# values to match
vals = unique(x)
# find all positions of all elements in the target vector
match_list = grr::matches(vals, x, list = TRUE)
# compute the lags, then put them in the appropriate place in the return vector
for(i in seq_along(match_list))
lag_counts[x == vals[i]] = c(first_time, diff(sort(match_list[[i]])))
# return vector
return(lag_counts)
}
compute_lag_counts(x)
虽然它似乎做了它应该做的,但我宁愿使用别人的高效,经过充分测试的解决方案!我的搜索结果是空的,这让我感到惊讶,因为这似乎是一项常见的任务。
这是一个可行的函数
compute_lag_counts <- function(x) {
seqs <- split(seq_along(x), x)
unsplit(Map(function(i) c(NA, diff(i)), seqs), x)
}
compute_lag_counts (x)
# [1] NA NA 2 NA 2 4 1 4 1 3 1 7 1 1 6 1 1 1 8 6
基本上,您使用 split()
来分隔索引,其中值出现在向量中的每个唯一值。然后我们使用它们出现的索引之间的差异来计算与前一个值的距离。然后我们使用 unstack
将这些值放回原来的顺序。
或
ave(seq.int(x), x, FUN = function(x) c(NA, diff(x)))
# [1] NA NA 2 NA 2 4 1 4 1 3 1 7 1 1 6 1 1 1 8 6
我们计算每组 x
的第一个 diff
指数误差。
一个data.table
选项感谢@Henrik
library(data.table)
dt = data.table(x)
dt[ , d := .I - shift(.I), x]
dt
一个选项dplyr
通过原始向量分组后取相邻序列元素的差值
library(dplyr)
tibble(v1) %>%
mutate(ind = row_number()) %>%
group_by(v1) %>%
mutate(new = ind - lag(ind)) %>%
pull(new)
#[1] NA NA 2 NA 2 4 1 4 1 3 1 7 1 1 6 1 1 1 8 6
数据
v1 <- c("A", "C", "A", "B", "A", "C", "C", "B", "B", "C", "C", "A",
"A", "A", "B", "B", "B", "B", "C", "A")
假设我有一个值向量,例如:
A C A B A C C B B C C A A A B B B B C A
我想为每个元素创建一个新向量,其中包含自上次看到该元素以来的元素数。所以,对于上面的向量,
NA NA 2 NA 2 4 1 4 1 3 1 7 1 1 6 1 1 1 8 6
(其中 NA
表示这是第一次看到该元素)。
比如第一个A和第二个A分别在1号位和3号位,相差2;第三个和第四个A在位置4和11,相差7,依此类推。
是否有预建的管道兼容函数可以执行此操作?
我把这个函数拼凑在一起来演示:
# For reproducibility
set.seed(1)
# Example vector
x = sample(LETTERS[1:3], size = 20, replace = TRUE)
compute_lag_counts = function(x, first_time = NA){
# return vector to fill
lag_counts = rep(-1, length(x))
# values to match
vals = unique(x)
# find all positions of all elements in the target vector
match_list = grr::matches(vals, x, list = TRUE)
# compute the lags, then put them in the appropriate place in the return vector
for(i in seq_along(match_list))
lag_counts[x == vals[i]] = c(first_time, diff(sort(match_list[[i]])))
# return vector
return(lag_counts)
}
compute_lag_counts(x)
虽然它似乎做了它应该做的,但我宁愿使用别人的高效,经过充分测试的解决方案!我的搜索结果是空的,这让我感到惊讶,因为这似乎是一项常见的任务。
这是一个可行的函数
compute_lag_counts <- function(x) {
seqs <- split(seq_along(x), x)
unsplit(Map(function(i) c(NA, diff(i)), seqs), x)
}
compute_lag_counts (x)
# [1] NA NA 2 NA 2 4 1 4 1 3 1 7 1 1 6 1 1 1 8 6
基本上,您使用 split()
来分隔索引,其中值出现在向量中的每个唯一值。然后我们使用它们出现的索引之间的差异来计算与前一个值的距离。然后我们使用 unstack
将这些值放回原来的顺序。
或
ave(seq.int(x), x, FUN = function(x) c(NA, diff(x)))
# [1] NA NA 2 NA 2 4 1 4 1 3 1 7 1 1 6 1 1 1 8 6
我们计算每组 x
的第一个 diff
指数误差。
一个data.table
选项感谢@Henrik
library(data.table)
dt = data.table(x)
dt[ , d := .I - shift(.I), x]
dt
一个选项dplyr
通过原始向量分组后取相邻序列元素的差值
library(dplyr)
tibble(v1) %>%
mutate(ind = row_number()) %>%
group_by(v1) %>%
mutate(new = ind - lag(ind)) %>%
pull(new)
#[1] NA NA 2 NA 2 4 1 4 1 3 1 7 1 1 6 1 1 1 8 6
数据
v1 <- c("A", "C", "A", "B", "A", "C", "C", "B", "B", "C", "C", "A",
"A", "A", "B", "B", "B", "B", "C", "A")