r - 识别相同值之间的序列
问题描述
我有一个大矩阵:
id v1 v2 v3 v4 v5 v6 v7 v8
1001 37 15 30 37 4 11 35 37
2111 44 31 44 30 24 39 44 18
3121 43 49 39 34 44 43 26 24
4532 45 31 26 33 12 47 37 15
5234 23 27 34 23 30 34 23 4
6345 9 46 39 34 8 43 26 24
对于每一行(id),我想确定列 v1 到 v8 中的数字间隔。区间在这里定义为以相同数字开头和结尾的数字序列。
例如,在第一行中,有两个以 37 开头和结尾的序列:从第 1 列到第 4 列(37、15、30、37 )和从第4列到第 8 列(37、4、11、35、37 ).
焦点值应该只出现在开始和结束位置。例如,在第一行中,从 V1 的 37 到 V8 的 37 的序列不包括在内,因为 37 也出现在 V4 中。
对于每个间隔,我想要开始和结束列的索引、焦点开始和结束值,以及它们之间的数字序列。
期望的输出:
1001 [v1] to [v4] 37 to 37: 15,30
1001 [v4] to [v8] 37 to 37: 4, 11, 35
2111 [v1] to [v3] 44 to 44: 31
2111 [v3] to [v7] 44 to 44: 30, 24, 39
有什么建议么?算法?
我设法为向量而不是矩阵的索引编写代码,
a <- which(x == 37)
from <- a[!(a-1) %in% a]
to <- a[!(a+1) %in% a]
rbind(from, to)
解决方案
非常暴力的方法。获取给定行的唯一元素,检查它们是否存在不止一次但不是并排存在,然后lapply
通过每个元素,获取x
它们之间的行的元素。
apply(m, 1, function(x) {
u <- unique(x)
u <- u[sapply(u, function(u) any(diff(which(x == u)) > 1))]
lapply(setNames(u, u), function(u){
ind <- which(x == u)
lapply(seq(length(ind) - 1),
function(i) x[seq(ind[i] + 1, ind[i + 1] - 1)])
})
})
输出:
# [[1]]
# [[1]]$`37`
# [[1]]$`37`[[1]]
# [1] 15 30
#
# [[1]]$`37`[[2]]
# [1] 4 11 35
#
#
#
# [[2]]
# [[2]]$`44`
# [[2]]$`44`[[1]]
# [1] 31
#
# [[2]]$`44`[[2]]
# [1] 30 24 39
#
#
#
# [[3]]
# [[3]]$`43`
# [[3]]$`43`[[1]]
# [1] 49 39 34 44
#
#
#
# [[4]]
# named list()
#
# [[5]]
# [[5]]$`23`
# [[5]]$`23`[[1]]
# [1] 27 34
#
# [[5]]$`23`[[2]]
# [1] 30 34
#
#
# [[5]]$`34`
# [[5]]$`34`[[1]]
# [1] 23 30
#
#
#
# [[6]]
# named list()
编辑:Henrik 的回答启发了我做一个基于加入的版本
library(data.table)
library(magrittr)
d <- melt(as.data.table(m), "id", variable.name = 'ci')[, ci := rowid(id)]
setorder(d, id)
options(datatable.nomatch = 0)
d[d, on = .(id, value, ci > ci)
, .(id, value, i.ci, x.ci)
, mult = 'first'] %>%
.[d, on = .(id, i.ci < ci, x.ci > ci)
, .(id, value, from_ci = x.i.ci, to_ci = x.x.ci, i.value)] %>%
.[, .(val = .(i.value))
, by = setdiff(names(.), 'i.value')]
# id value from_ci to_ci val
# 1: 1001 37 1 4 15,30
# 2: 1001 37 4 8 4,11,35
# 3: 2111 44 1 3 31
# 4: 2111 44 3 7 30,24,39
# 5: 3121 43 1 6 49,39,34,44
# 6: 5234 23 1 4 27,34
# 7: 5234 34 3 6 23,30
# 8: 5234 23 4 7 30,34
推荐阅读
- python - 哪个 Python 代码更好用?或者为此无关紧要
- javascript - Node.js 发送电子邮件模板 ejs 使用 flexbox
- html - CSS选择第三个相邻元素
- java - 无法在 Eclipse 中启动 Tomcat v9.0 服务器
- sql - 带有连接的 PostgreSQL Select 语句
- excel - VBA excel循环遍历一个范围以从列中拆分名称
- ios - 在为 iOS 编译时,如何让 Unity 自动添加 Sign In With Apple 功能?
- lua - Garry's Mod Lua:如何进行延迟/冷却?
- python - 破坏了我的 python 安装,重新安装并不能解决问题
- mongodb - 使用带有条件的 $group 管道进行聚合