我在 R 中有一个巨大的数据框,看起来像这样:
数据框1
身份证 | 开始 | 停止 |
---|---|---|
+ | 3 | 5 |
- | 9 | 13 |
我还有另一个数据框,看起来像这样:
数据框2
身份证 | 名字 | 位置 |
---|---|---|
- | 你好 | 4 |
+ | 那里 | 7 |
- | 我的 | 11 |
+ | 名字 | 12 |
我想要做的是对于数据帧 1 中的每一行,我想确定它在给定范围内的“距离”,或者如果它不属于某个范围或“ID”(+/-) 不属于某个范围,则打印 NA匹配。所以输出会是这样的:
身份证 | 名字 | 位置 | 相对位置 |
---|---|---|---|
- | 你好 | 4 | 2 |
+ | 那里 | 7 | 不适用 |
- | 我的 | 12 | 3 |
+ | 名字 | 12 | 不适用 |
我目前有一个相对较长的循环,使用 apply() 和几层 if 函数来运行这个过程。我遇到的问题是我需要对多个非常大的数据帧(大小为千兆字节)执行此操作,因此效率是关键。完成这个过程最有效的方法是什么?
我也尝试过 cut() 函数,但我不知道如何打印我想要的结果或如何使间隔不连续。即使它有效,我也不知道它是否会更有效。
主要是判断多个位置是否处于区间的问题。这是一个算法问题。
这是一种有效的算法来查找所有位置的包含间隔。我将距离的计算和结果的正确格式留在练习中;-)(从这个画布上应该很容易)。
library(data.table)
## DF1
intervals <- data.table(id = c('+', '-'),
start = c(3, 9),
end = c(5, 13))
## DF2
values <- data.table(id = c('-', '+', '-', '+'),
name = c("hello", "there", "my", "name"),
pos = c(4, 7, 12, 12))
## The trick is to sort by position everything,
## `type` is 0 if it is an interval start position,
## 1 = interval end position, and
## 2 = is a position in `values`
## `id` is the index (row number) either in `intervals` or `values`
n.interval <- nrow(intervals)
dt <- rbind(data.table(id = 1:n.interval, pos = intervals$start, type = 0),
data.table(id = 1:n.interval, pos = intervals$end, type = 1),
data.table(id = 1:nrow(values), pos = values$pos, type = 2))
setorder(dt, pos)
len <- nrow(dt)
## A stack that will contain the interval row number
depth <- 0
stack <- numeric(16384)
## loop over the rows of `dt`
for (i in 1:len)
{
if ( 0 == dt$type[i] ) ## start
{
depth <- depth + 1
## add on stack the row numbre of the interval
stack[depth] <- dt$id[i]
}
else if ( 1 == dt$type[i] && 0 < depth ) ## end
{
## pop from the stack
depth <- depth - 1
}
else if ( 2 == dt$type[i]) ## Value
{
cat("=====\nThe value:\n")
value.id <- dt$id[i]
print(values[value.id,])
if ( 0 < depth )
{
## the intervals on the `stack` all contain the current value
index <- stack[depth]
cat("\nis inside this interval (most imbricated):\n")
print(intervals[index,])
} else {
cat("\nis outside any interval\n\n")
}
} else {
warning("should not be here")
break
}
}