You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

R语言:基于另一数据框的时间区间为数据框添加列

嘿,我懂你的问题啦——你本来想给DF添加一列标记,判断每行的Time是否落在StartEnd里的任意一个区间,但用mapply跑出来的结果是个矩阵,完全不是想要的单列,对吧?

为啥会返回矩阵?

mapply会对StartEnd里的每一组Start和End单独生成一个和DF$Time长度一致的0/1向量,最后把这些向量按列拼起来,所以你得到了4列的矩阵(刚好对应StartEnd的4行)。而我们需要的是只要Time落在任意一个区间就标记1,否则0,所以得把这个矩阵的行结果合并起来。

几种解决方法:

方法1:用rowSums快速处理矩阵结果

这是最直接的修正方案,利用rowSums计算每行的和——只要行和大于0,就说明这个Time至少落在一个区间里,再转成1/0格式:

DF <- data.frame(Time=c(1:20))
StartEnd <- data.frame(Start=c(2,6,14,19), End=c(4,10,17,20))

# 修正后的代码
DF$Activity <- as.integer(rowSums(
  mapply(FUN = function(Start,End) DF$Time >= Start & DF$Time <= End, 
         Start=StartEnd$Start, End=StartEnd$End)
) > 0)

运行后DF$Activity就是你要的单列标记:比如Time=2-4、6-10、14-17、19-20这些行的Activity都是1,其余是0。

方法2:直接遍历每个Time值判断

如果觉得矩阵处理有点绕,也可以直接对每个Time值检查是否在任意区间里,用sapply实现:

DF$Activity <- as.integer(
  sapply(DF$Time, function(t) {
    any(t >= StartEnd$Start & t <= StartEnd$End)
  })
)

这里any()函数会判断当前Time是否满足至少一个区间条件,返回TRUE/FALSE,再用as.integer()转成1/0。

方法3:用data.table做高效区间匹配(适合大数据)

如果你的数据量很大,用data.table的区间匹配功能会更高效:

library(data.table)
setDT(DF)
setDT(StartEnd)

# 给DF加一个临时的End列(和Time相等,变成单元素区间)
DF[, temp_end := Time]
# 设置StartEnd的键用于区间匹配
setkey(StartEnd, Start, End)
# 用foverlaps找落在任意区间内的行
overlaps <- foverlaps(DF, StartEnd, by.x = c("Time", "temp_end"), type = "within")
# 标记:匹配到的行Activity为1,否则0
DF$Activity <- as.integer(!is.na(overlaps$Start))
# 删掉临时列
DF[, temp_end := NULL]

这样不管哪种方法,都能得到你想要的单列标记啦~

内容的提问来源于stack exchange,提问作者user3640617

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 07:53:59