r - 如何在dplyr中使用多列实现一个函数

标签 r dplyr

这个问题之前被问过: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 在列上循环。我们需要 rowwisec_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/

相关文章:

r - 如何在R中将简体中文转换为繁体中文?

在 R 中使用多个标题行 reshape 数据

R,使用 dplyr::filter() 和 %in% 将列名作为参数传递给函数

r - 获取 dplyr 管道结构中最常出现的因子水平

r - 在 Shiny 中使用带有反应式数据集的 dplyr 输入变量时出现问题

r - 使用R在 map 中绘制电子邮件流

python - 使用 R 或 Matplotlib (Python),如何根据 CSV 文件每一行的值比较创建维恩图?

r - 如何对 `` dplyr `` or ` `tidyr`` 中的多列进行 rowSums?

r - 如何根据列表中每个元素的名称使用map_if

r - 翻转 gg TreeMap