R语言实现按相邻列非NA行求和并计算列间比值
解决方案:R语言列求和与比值计算并添加结果行
需求回顾
对给定的data.frame完成以下操作:
- 每列仅求和到相邻右侧列无NA的行
- 计算每列求和值与前一列的比值(第一列比值为1)
- 在原表格末尾添加一行展示这些比值
原始数据
表格形式
| 日期 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|---|---|---|---|---|---|---|---|
| 07/10/2021 | 20 | 25 | 25 | 26 | 26 | 25 | 31 |
| 08/10/2021 | 26 | 25 | 25 | 26 | 25 | 31 | |
| 09/10/2021 | 29 | 29 | 25 | 26 | 39 | ||
| 10/10/2021 | 20 | 29 | 25 | 31 | |||
| 11/10/2021 | 20 | 30 | 30 | ||||
| 12/10/2021 | 30 | 30 | |||||
| 1/10/2022 | 39 |
R数据结构
# 示例数据 d d <- structure(list(Date = c("07.10.2021", "08.10.2021", "09.10.2021", "10.10.2021", "11.10.2021", "12.10.2021", "01.10.2022"), X1 = c(20L, 26L, 29L, 20L, 20L, 30L, 39L), X2 = c(25L, 25L, 29L, 29L, 30L, 30L, NA), X3 = c(25L, 25L, 25L, 25L, 30L, NA, NA), X4 = c(26L, 26L, 26L, 31L, NA, NA, NA), X5 = c(26L, 25L, 39L, NA, NA, NA, NA), X6 = c(25L, 31L, NA, NA, NA, NA, NA), X7 = c(31L, NA, NA, NA, NA, NA, NA)), class = "data.frame", row.names = c(NA, 7L))
用户尝试的函数(未成功)
f <- function(.x, .y) { keep_rows <- cumsum(is.na(.y)) == 0 sum(.x[keep_rows]) }
可行代码实现
思路
- 分离数值列与日期列,避免日期干扰计算
- 遍历每一列:
- 对于非最后一列,筛选出右侧列未出现NA的行(用
cumsum(is.na(右侧列)) == 0判断),然后求和 - 最后一列直接求和所有非NA值
- 对于非最后一列,筛选出右侧列未出现NA的行(用
- 计算各列比值:第一列设为1,后续列用当前列求和值除以前一列求和值,保留两位小数
- 将比值行合并到原数据框中
完整代码
# 提取数值列(排除Date列) num_cols <- d[, !names(d) %in% "Date"] # 初始化求和向量 col_sums <- numeric(ncol(num_cols)) # 计算每列的有效求和值 for (i in seq_len(ncol(num_cols))) { if (i < ncol(num_cols)) { # 保留右侧列无NA的行 valid_rows <- cumsum(is.na(num_cols[, i+1])) == 0 col_sums[i] <- sum(num_cols[valid_rows, i], na.rm = TRUE) } else { # 最后一列求和所有非NA值 col_sums[i] <- sum(num_cols[, i], na.rm = TRUE) } } # 计算比值 ratios <- c(1, round(col_sums[-1] / col_sums[-length(col_sums)], 2)) # 创建结果行并合并 result_row <- data.frame(Date = "TOTAL", t(ratios)) names(result_row)[-1] <- names(num_cols) final_d <- rbind(d, result_row) # 查看结果 print(final_d)
输出结果
运行代码后得到的最终表格如下:
| 日期 | X1 | X2 | X3 | X4 | X5 | X6 | X7 |
|---|---|---|---|---|---|---|---|
| 07.10.2021 | 20 | 25 | 25 | 26 | 26 | 25 | 31 |
| 08.10.2021 | 26 | 25 | 25 | 26 | 25 | 31 | NA |
| 09.10.2021 | 29 | 29 | 25 | 26 | 39 | NA | NA |
| 10.10.2021 | 20 | 29 | 25 | 31 | NA | NA | NA |
| 11.10.2021 | 20 | 30 | 30 | NA | NA | NA | NA |
| 12.10.2021 | 30 | 30 | NA | NA | NA | NA | NA |
| 01.10.2022 | 39 | NA | NA | NA | NA | NA | NA |
| TOTAL | 1 | 1.10 | 0.94 | 1.09 | 1.15 | 1.09 | 1.24 |
内容的提问来源于stack exchange,提问作者nwk123
相关产品推荐
相关产品推荐

