R语言实现:每行末观测值减首值除以非空单元格数并生成新列
R语言逐行计算自定义指标方案
计算规则
逐行对数据框执行以下运算,结果存入数据新列:
- 取当前行最后一个非NA的观测值
- 取当前行第一个观测值
- 统计当前行非NA有效值的总数量
- 最终计算逻辑:
(最后一个非NA值 - 首个观测值) / 非NA有效值总数
测试数据
示例数据集列范围为Day1至Day5,结构如下:
df <- data.frame( Day1 = c(3, 3, 5, 7), day2 = c(2, 4, 6, 8), day3 = c(1, NA, 7, 9), day4 = c(1, NA, NA, 10), day5 = c(1, NA, NA, 12) )
对应各行预期计算逻辑:
- 第一行:
(1-3)/5 = -0.4 - 第二行:
(4-3)/2 = 0.5 - 第三行:
(7-5)/3 ≈ 0.6667 - 第四行:
(12-7)/5 = 1
实现代码
Base R 版本(无第三方包依赖)
用apply做逐行遍历即可,不需要提前固定列位置,自动适配每行NA的分布:
df$calc_result <- apply(df, 1, function(row) { valid <- row[!is.na(row)] (tail(valid, 1) - valid[1]) / length(valid) })
运行后输出结果验证:
> df Day1 day2 day3 day4 day5 calc_result 1 3 2 1 1 1 -0.4000000 2 3 4 NA NA NA 0.5000000 3 5 6 7 NA NA 0.6666667 4 7 8 9 10 12 1.0000000
和预期结果完全匹配。
Tidyverse 版本
如果使用tidyverse生态工作流,可通过rowwise+c_across实现:
library(dplyr) df <- df %>% rowwise() %>% mutate( valid_set = list(c_across(everything())[!is.na(c_across(everything()))]), calc_result = (last(valid_set) - first(valid_set)) / length(valid_set) ) %>% select(-valid_set) %>% ungroup()
注意事项
- 如果存在整行全为NA的情况,上述代码会返回
NaN,可根据业务需求在函数内加判断分支单独处理 - 代码自动适配任意列数的输入数据,不需要手动修改列索引
内容的提问来源于stack exchange,提问作者MarkusFrost
相关产品推荐
相关产品推荐

