这个问题之前被问过:How to round numbers of a data frame in R preserving the sum?
我还想在 dplyr 中实现这个函数,它根据所需的位数进行舍入并保持统一:
round_preserve_sum <- function(x, digits = 0) {
up <- 10 ^ digits
x <- x * up
y <- floor(x)
indices <- tail(order(x-y), round(sum(x)) - sum(y))
y[indices] <- y[indices] + 1
y / up
}
这是一个数据框:
df <- data.frame(SAND = c(0.00000, 28.00000, 27.27273),
SILT = c(45.45455, 35.00000, 34.34343),
CLAY = c(54.54545, 37.00000, 38.38384))
分别使用这个函数和这些值,我得到:
round_preserve_sum(c(0.00000, 45.45455, 54.54545), 0)
[1] 0 45 55
round_preserve_sum(c(28.00000, 35.00000, 37.00000), 0)
[1] 28 35 37
round_preserve_sum(c(27.27273, 34.34343, 38.38384), 0)
[1] 27 34 39
总和为 100
当我在 dplyr 中实现这个功能时:
df.Rd0 <-df %>%
mutate(across(c(SAND, SILT, CLAY), ~round_preserve_sum(.,0)),
Sum = SAND + SILT + CLAY)
我明白了:
SAND SILT CLAY Sum
1 0 46 55 101
2 28 35 37 100
3 27 34 38 99
不使用代字号:
df.Rd0 <-df %>%
mutate(across(c(SAND, SILT, CLAY), round_preserve_sum(.,0)),
Sum = SAND + SILT + CLAY)
我收到此错误消息:
Error : Problem with `mutate()` input `..1`.
i `..1 = across(c(SAND, SILT, CLAY), round_preserve_sum(., 0))`.
x undefined columns selected
我猜这个函数不是为向量编程的?
最佳答案
~
是一个 lambda 表达式,即 function(.x)
的缩写形式。如果我们不使用它,则将格式参数指定为named one
library(dplyr)
df %>%
mutate(across(c(SAND, SILT, CLAY), round_preserve_sum, digits = 0),
Sum = SAND + SILT + CLAY)
-输出
SAND SILT CLAY Sum
1 0 46 55 101
2 28 35 37 100
3 27 34 38 99
关于 OP 手动使用将总和设为 100,它是 rowwise
,而不是 column wise - across
在列上循环。我们需要 rowwise
和 c_across
df %>%
rowwise %>%
mutate(Sum = sum(round_preserve_sum(c_across(everything()), 0))) %>%
ungroup
-输出
# A tibble: 3 x 4
SAND SILT CLAY Sum
<dbl> <dbl> <dbl> <dbl>
1 0 45.5 54.5 100
2 28 35 37 100
3 27.3 34.3 38.4 100
如果我们想要将四舍五入的列与总和一起返回,请使用 pmap
library(purrr)
df %>%
pmap_dfr(~ {tmp <- round_preserve_sum(c(...), 0)
c(tmp, Sum = sum(tmp))})
# A tibble: 3 x 4
SAND SILT CLAY Sum
<dbl> <dbl> <dbl> <dbl>
1 0 45 55 100
2 28 35 37 100
3 27 34 39 100
这可以通过 collapse
中的 dapply
变得更快
library(collapse)
df <- dapply(df, MARGIN = 1, FUN = round_preserve_sum, 0)
df$Sum <- rowSums(df, na.rm = TRUE)
关于r - 如何在dplyr中使用多列实现一个函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68672570/