r - 向量中不同元素之间的元素数
问题描述
假设我有一个值向量,例如:
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分别在位置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)
尽管它似乎做了它应该做的事情,但我宁愿使用别人的高效、经过良好测试的解决方案!我的搜索结果是空的,这让我感到惊讶,因为这似乎是一项常见的任务。
解决方案
或者
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
我们计算diff
每组 的索引的第一个 erence x
。
data.table
感谢@Henrik的一个选项
library(data.table)
dt = data.table(x)
dt[ , d := .I - shift(.I), x]
dt
推荐阅读
- python - 为什么 for 循环阶乘函数比递归阶乘函数快?
- laravel - 如何在 laravel 中添加插件
- cordova - 处理第二页的按钮点击事件以确定第一页的结果,Ionic
- angular - 使用 Angular 2 启动虚拟机
- postgresql - liferay 7.1 PostgreSQL 兼容性
- java - HttpServletRequest 到 MultipartHttpServletRequest:Junit 中的 ClassCastException
- ruby - 随机报价生成器重复相同的报价,为什么?
- javascript - x 轴上的条形位置
- java - 连接 CDI bean 和业务逻辑
- odoo - Odoo:根据模型中另一个字段的值在树视图中显示一个字段