R语言合并不同长度数据框:重复较短表行直至参数或时间戳变更
方案1:滚动左连接(dplyr 1.1.0及以上版本推荐,最简写法)
直接利用dplyr内置的滚动连接逻辑,匹配每个追踪数据行对应的最近刺激参数:
library(tidyverse) # 你的示例数据生成代码(无需修改) set.seed(123) gratingspeed <- c(sample(c(-3:3), 10, replace=TRUE)) gratingfreq <- sample(c(-2, -1, 0.5, 0.5, 1, 2), 10, replace=TRUE) timestamp <- runif(10, min=0, max=25) timestamp[1] <- 0 stimuli <- data.frame(gratingspeed, gratingfreq, timestamp) stimuli <- arrange(stimuli, stimuli$timestamp) timemultiplier <- c(rep(c(-1,1), 5)) stimuli <- cbind(timemultiplier, stimuli) stimuli$dfid <- row_number(stimuli$timestamp) trackingx <- runif(25, min=0, max=800) trackingy <- runif(25, min=0, max=800) boutsuccess <- sample(c(rep(TRUE, 23), rep(FALSE, 2)), 25 ,replace = T) timestamp <- c(1:25) trackingdata <- cbind(trackingx, trackingy, boutsuccess, timestamp) trackingdata <- as.data.frame(trackingdata) trackingdata$dfid <- NA # 核心连接代码 result <- trackingdata %>% left_join(stimuli, join_by(closest(timestamp >= timestamp)), suffix = c("_tracking", "_stimuli"))
连接逻辑:对每一行追踪数据的时间戳,匹配刺激参数表中小于等于该时间戳的最大时间戳对应的行,自动填充对应刺激参数,完全符合你要求的「重复刺激行直到下一个参数变更点」的需求。
方案2:填充法(兼容旧版dplyr,符合你原有处理逻辑)
如果你用的dplyr版本低于1.1.0,可以用你原本的合并后排序+向下填充的思路实现:
# 合并两个表后按时间排序 trialdata <- bind_rows( stimuli %>% mutate(data_type = "stimuli"), trackingdata %>% mutate(data_type = "tracking") ) %>% arrange(timestamp) %>% # 向下填充刺激参数和dfid,直到下一个刺激变更点 fill(dfid, timemultiplier, gratingspeed, gratingfreq, .direction = "down") %>% # 过滤只保留追踪数据行,就是最终合并结果 filter(data_type == "tracking")
该方案不需要手动构造公共连接列,fill()函数会自动把前面出现的刺激参数填充到后续所有追踪数据行,遇到新的刺激时间点自动更新参数。
内容的提问来源于stack exchange,提问作者Molly Westbrook
相关产品推荐
相关产品推荐

