如何用summarise_all提取各列首末非NA值的索引与日期并格式化输出
问题处理方案
需求回顾
现有一个tibble类型的数据框df,第一列为日期列Date,其余列为时间序列变量。需要提取每个时间序列列的:
- 首个非NA观测值的索引(行号)
- 首个非NA观测值对应的日期
- 末个非NA观测值的索引(行号)
- 末个非NA观测值对应的日期
最终生成的新数据框需满足:每列对应原数据的一个时间序列变量,上述四个信息分四行存储。
原代码仅能提取首末索引,且每个变量对应两列、结果仅一行,需要进一步调整格式并补充日期信息。
解决方案代码
1. 构造示例数据(用于测试)
library(tibble) library(dplyr) library(tidyr) set.seed(123) df <- tibble( Date = seq(as.Date("2023-01-01"), as.Date("2023-01-10"), by = "day"), Var1 = c(NA, NA, 3, 4, 5, NA, 7, 8, NA, NA), Var2 = c(10, NA, NA, 13, 14, 15, NA, NA, 18, NA), Var3 = rep(NA, 10) # 全NA的变量,用于测试边界情况 )
2. 核心处理代码
result_df <- df %>% # 对每个时间序列变量计算四个目标值,兼容全NA情况 summarise(across(-Date, list( first_idx = ~ifelse(all(is.na(.)), NA_integer_, min(which(!is.na(.)))), first_date = ~ifelse(all(is.na(.)), NA_Date_, Date[min(which(!is.na(.)))]), last_idx = ~ifelse(all(is.na(.)), NA_integer_, max(which(!is.na(.)))), last_date = ~ifelse(all(is.na(.)), NA_Date_, Date[max(which(!is.na(.)))]) ))) %>% # 将宽表转成长表,拆分列名为变量名和指标类型 pivot_longer(everything(), names_to = c("Variable", "Metric"), names_sep = "_", values_to = "Value") %>% # 将长表转回宽表,以指标类型为行、原变量为列 pivot_wider(names_from = Variable, values_from = Value) %>% # 将指标类型列移到第一列,提升可读性 relocate(Metric, everything())
3. 输出结果示例
运行上述代码后,result_df的结构如下:
# A tibble: 4 × 4 Metric Var1 Var2 Var3 <chr> <chr> <chr> <chr> 1 first_idx 3 1 NA 2 first_date 2023-01-03 2023-01-01 NA 3 last_idx 8 9 NA 4 last_date 2023-01-08 2023-01-09 NA
步骤解释
summarise(across(...)):跳过Date列,对每个时间序列变量同时计算四个指标,通过ifelse处理全NA的边界情况,避免报错。pivot_longer:将原结果中每个变量对应的四列(如Var1_first_idx)拆分为变量名、指标类型、值三列,把宽表转换为长表格式,方便后续重组。pivot_wider:将长表重新转换为宽表,以指标类型(first_idx/first_date等)作为行,原时间序列变量作为列,完全匹配需求格式。relocate:调整列顺序,把Metric列放在最前面,让结果更易读。
内容的提问来源于stack exchange,提问作者erised
相关产品推荐
相关产品推荐

