R语言如何将dataframe列的前导0替换为后续紧邻非0数值
帧编号列补全实现方案
问题背景
现有一个dataframe,其中frame列存储帧编号,结构示例如下:
核心列示例数据:
df <- structure(list(frame = c(0L, 0L, 0L, 0L, 473047L, 0L, 473049L,0L, 0L, 473051L, 0L, 0L, 473052L, 0L, 473055L)), row.names = c(NA, -15L), class = "data.frame")
列中0值和其后出现的第一个非0值属于同一帧,需要将所有0替换为对应的后续非0帧号:开头4个0替换为473047,第6行的0替换为473049,第8-9行的0替换为473051,以此类推完成全列替换。
最初的实现思路是通过反向遍历的for循环完成替换:
遍历frame列的每一行 如果当前值大于0,记录该值 如果当前值为0,将其替换为最近一次记录的非0值
实现方案
不需要编写复杂的循环逻辑,以下是base R和tidyverse两种高效的向量化实现:
方法1:tidyverse 实现(代码最简洁)
核心逻辑是先将0转换为缺失值,再向数据开头方向(向上)用后续的非0值填充缺失值:
library(tidyverse) df <- df %>% mutate(frame = na_if(frame, 0)) %>% # 将0替换为NA fill(frame, .direction = "up") # 向上填充NA
运行后frame列结果如下,完全匹配需求:
[1] 473047 473047 473047 473047 473047 473049 473049 473051 473051 473051 473052 [12] 473052 473052 473055 473055
方法2:base R 实现(无第三方包依赖)
通过定位非0值位置,用区间匹配给每一行分配对应的帧号,不需要加载任何扩展包:
# 提取所有非0帧号的位置和对应值 non_zero_pos <- which(df$frame != 0) non_zero_val <- df$frame[non_zero_pos] # 为每一行匹配所属帧号 df$frame <- non_zero_val[findInterval(seq_len(nrow(df)), non_zero_pos, left.open = TRUE) + 1]
运行结果和tidyverse方法完全一致。
附:对应原始思路的for循环实现(不推荐)
如果要完全按照反向遍历的思路写for循环,可以参考以下代码,但该方法是逐行运算,数据量大时性能远差于上述两种向量化方案:
# 初始化记录值为最后一个非0帧号,处理末尾的0 current_frame <- tail(df$frame[df$frame != 0], 1) # 从最后一行反向遍历到第一行 for (i in nrow(df):1) { if (df$frame[i] != 0) { current_frame <- df$frame[i] } else { df$frame[i] <- current_frame } }
内容的提问来源于stack exchange,提问作者codegoblin1996
相关产品推荐
相关产品推荐

