使用zoo::na.locf填充字符串NA时处理开头NA的问题
数据框列表NA值向前填充问题解决
问题场景
现有一个包含多个tibble的数据框列表,部分数据框的目标列存在开头为NA的情况,需要对NA值进行向前填充(用上一个非NA值填充后续NA),但保留开头的NA。示例数据如下:
test_dat <- structure(list(...5 = c("euro", "euro", NA, NA, NA, NA, NA, "dollar", NA)), row.names = c(NA, -9L), class = c("tbl_df", "tbl", "data.frame")) test_dat2 <- structure(list(...5 = c(NA, "euro", NA, NA, NA, NA, NA, "dollar", NA)), row.names = c(NA, -9L), class = c("tbl_df", "tbl", "data.frame")) l = list(test_dat , test_dat2)
尝试使用zoo::na.locf填充时触发报错:
for (i in seq_along(l)){ l[[i]][1] <- zoo::na.locf(l[[i]][1]) }
报错信息:
Error: ! Assigned data `zoo::na.locf(l[[i]][1])` must be compatible with existing data. ✖ Existing data has 9 rows. ✖ Assigned data has 8 rows. ℹ Only vectors of size 1 are recycled. Run `rlang::last_error()` to see where the error occurred.
添加na.rm=TRUE参数后问题仍未解决,期望填充后test_dat2的结果如下:
# A tibble: 9 × 1 ...5 <chr> 1 NA 2 euro 3 euro 4 euro 5 euro 6 euro 7 euro 8 dollar 9 dollar
报错原因
- 使用
na.rm=TRUE时,na.locf会直接移除结果中的所有NA值,导致返回的向量长度短于原数据列,无法匹配赋值; - 用
l[[i]][1]选取列会返回子tibble而非向量,na.locf处理这类对象时易出现长度异常(正确列选取方式应为l[[i]][[1]]或l[[i]]$...5)。
解决方案
使用na.locf时保持默认的na.rm=FALSE(保留开头的NA),同时确保选取的是列向量而非子数据框,即可保证返回结果长度与原列一致。
方案1:循环实现
library(zoo) for (i in seq_along(l)) { # 选取列向量并向前填充NA,保留开头NA l[[i]][[1]] <- na.locf(l[[i]][[1]], na.rm = FALSE) }
方案2:函数式实现(更简洁)
library(zoo) library(purrr) library(dplyr) l_filled <- map(l, ~ mutate(., ...5 = na.locf(...5, na.rm = FALSE)))
验证结果
处理后test_dat2的输出与预期完全一致:
l_filled[[2]] # A tibble: 9 × 1 ...5 <chr> 1 NA 2 euro 3 euro 4 euro 5 euro 6 euro 7 euro 8 dollar 9 dollar
内容的提问来源于stack exchange,提问作者Tom
相关产品推荐
相关产品推荐

