我正在尝试将数据表中的列相加,直到相邻列的值为 NA。例如,如果我有桌子:
日期 | 1 | 2 | 3 |
---|---|---|---|
2022年7月1日 | 2 | 12 | 12 |
2022年8月1日 | 1 | 1 | 不适用 |
2022年9月1日 | 3 | 不适用 | 不适用 |
我只会将第 1 列中的第 2 行相加,因为第 2 列中的第 3 行是 NA,而第 2 列中的第 1 行是 NA。然后我会将这些列中的每一列除以前一列。我还想忽略日期。有没有一种方法可以在不进行硬编码的情况下做到这一点?这将是所需的结束行:
总计 | 3 | 12 | 12 |
---|
我尝试使用“adorn_table”并排除 NA,但这似乎不起作用。
对于原来的问题,请尝试:
library(tidyverse)
# create made-up data
df <- tibble(
x = c(2, 1, 3),
y = c(12, 1, NA)
)
df |>
filter(cumsum(is.na(y)) == 0) |> # This will get rid of all rows starting from the first time when y is NA
summarize( # add up the values of x
s = sum(x)
) |>
pull(s)
对于澄清的问题,我假设列数是任意的。
library(tidyverse)
# create a function to do the work
f <- function(.x, .y) {
keep_rows <- cumsum(is.na(.y)) == 0
sum(.x[keep_rows])
}
# create made-up data
df <- tibble(
date = 1:3, # dates in your case, I'm keeping it simple
x = c(2, 1, 3),
y = c(12, 1, NA),
z = c(12, NA, NA)
)
total_row <- map2(
df |> select(x:z), # select the columns being summed
df |> select(y, z1 = z, z2 = z), # If you want the last column to depend on itself, you'll need to do something like this
f
)
bind_rows(df |>
mutate(date = as.character(date)),
c(date = "Total", total_row)
)
1) 定义一个函数
sumToNA
,将 x 与 y 中第一个 NA 之前的位置相加。如果没有 NA,则将 x 全部相加。
然后将该函数映射到没有第 1 列的 DF 和没有前两列但最后一列的 DF 两次。没有使用任何封装。
sumToNA <- function(x, y) sum(x[!cummax(is.na(y))], na.rm = TRUE)
n <- ncol(DF)
rbind(DF, c("Total", mapply(sumToNA, DF[2:n], DF[c(3:n, n)])))
## DATE 1 2 3
## 1 07/01/2022 2 12 12
## 2 08/01/2022 1 1 <NA>
## 3 09/01/2022 3 <NA> <NA>
## 4 Total 3 12 12
2) 定义一个函数
NAfwd
,它接受一个向量并返回它,但在第一个 NA 之后包含所有 NA,并将所有剩余的非 NA 转换为 0。然后将 DF[-1] 添加到处理后的 DF(没有第一个 NA)用 NAfwd
变换每列后,将两列和最后一列两次。然后使用 rowSums
对该行进行求和并将结果作为新行插入。
NAfwd <- \(z) 0 * Reduce(\(x, y) if (is.na(x)) x else y, z, acc = TRUE)
n <- ncol(DF)
rbind(DF, c("Total", colSums(DF[-1] + apply(DF[c(3:n,n)], 2, NAfwd), na.rm=TRUE)))
## DATE 1 2 3
## 1 07/01/2022 2 12 12
## 2 08/01/2022 1 1 <NA>
## 3 09/01/2022 3 <NA> <NA>
## 4 Total 3 12 12
DF <- data.frame(
DATE = c("07/01/2022", "08/01/2022", "09/01/2022"),
`1` = c(2L, 1L, 3L),
`2` = c(12L, 1L, NA),
`3` = c(12L, NA, NA),
check.names = FALSE
)