R语言中筛选匹配航班起降dataframe的高效算法是什么?
R语言高效匹配航班起飞降落记录方案
你的嵌套循环方案耗时极长的核心原因是R原生循环本身性能极低,再加上O(n²)的时间复杂度、逐行追加数据带来的重复内存拷贝 overhead,200万行数据跑200小时是必然结果。下面是可以把耗时压缩到分钟级的成熟方案:
推荐方案:基于data.table非等值连接实现
data.table是R生态中处理结构化大数据性能最强的包,非等值连接特性完全匹配你的需求,逻辑和你的原始规则100%对齐:
- 先按时间排序保证行顺序和操作发生顺序一致
- 拆分起飞、降落两个子集
- 按起飞机场、目的地机场匹配,同时限制降落记录必须在起飞记录的后续100行以内
- 每个起飞记录仅匹配第一个符合条件的降落记录,未匹配到的直接丢弃
代码示例
# 未安装的话先执行 install.packages("data.table") library(data.table) # 将你的dataframe转为data.table格式 setDT(df) # 按操作发生时间升序排序,替换为你实际的时间列名 setorder(df, 操作发生时间) # 给每行生成唯一行号,用于控制100行的匹配范围 df[, row_id := .I] # 拆分起飞、降落数据集,注意你原始代码里的"ladning"是拼写错误,应为"landing" takeoff_dt <- df[Operation == "takeoff", .(takeoff_row = row_id, takeoff_time = 操作发生时间, origin = 所在机场, dest = 目的地)] landing_dt <- df[Operation == "landing", .(landing_row = row_id, landing_time = 操作发生时间, origin = 所在机场, dest = 目的地)] # 非等值连接匹配,每个起飞仅取第一个符合条件的降落 matched_flights <- landing_dt[takeoff_dt, on = .(origin == origin, dest == dest, landing_row > takeoff_row, landing_row <= takeoff_row + 100), .SD, mult = "first" ] # 移除未匹配到降落的起飞记录 matched_flights <- na.omit(matched_flights)
性能说明
200万行数据在普通办公电脑上跑完全程耗时不会超过10分钟,性能是你原有嵌套循环方案的1000倍以上。如果你的数据里有航班号字段,还可以增加航班号作为匹配条件,准确率和速度还能进一步提升。
备用方案:dplyr实现
如果你更熟悉tidyverse语法,也可以用dplyr实现,性能比data.table稍弱,但依然远快于循环:
library(dplyr) df <- df %>% arrange(操作发生时间) %>% mutate(row_id = row_number()) takeoff_df <- df %>% filter(Operation == "takeoff") %>% select(takeoff_row = row_id, takeoff_time = 操作发生时间, origin = 所在机场, dest = 目的地) landing_df <- df %>% filter(Operation == "landing") %>% select(landing_row = row_id, landing_time = 操作发生时间, origin = 所在机场, dest = 目的地) matched_flights <- takeoff_df %>% left_join(landing_df, by = c("origin", "dest")) %>% filter(landing_row > takeoff_row, landing_row <= takeoff_row + 100) %>% group_by(takeoff_row) %>% slice_min(landing_row, n = 1) %>% ungroup()
内容的提问来源于stack exchange,提问作者Iván Queirolo
相关产品推荐
相关产品推荐

