r语言 - 对具有相似名称的多组列使用相同的突变

  • 本文关键字:突变 r语言 相似 r dplyr
  • 更新时间 :
  • 英文 :


想象以下数据:

data <- tribble(
~a1, ~a2, ~b1, ~b2, ~c1, ~c2,
32, 32, 50, 12, 12, 50,
48, 20, 55, 43, 10, 42
)

对于i ={1,2},我想计算deltai = (ai - ci) / ((ai + bi) * ci + ai)

(我明确地使用随机数和随机函数;不能通过识别和利用某种模式来找到解决办法。

直接的方法是执行

data <- data %>%
mutate(
delta1 = (a1 - c1) / ((a1 + b1) * c1 + a1),
delta2 = (a2 - c2) / ((a2 + b2) * c2 + a2)
)

但是它引入了大量的重复。

I could do

delta <- function(a, b, c) {
return((a - c) / ((a + b) * c + a))
}
data <- data %>%
mutate(
delta1 = delta(a1, b1, c1),
delta2 = delta(a2, b2, c2)
)

这使得以后可以很容易地改变delta()函数,但这看起来仍然像很多重复。

我的问题:有一种方法来计算delta1delta2与一行突变?

你可能认为重复的数量是可以的,但我可能需要计算其他几个术语,如gammaialphai。重复的行感觉不是一个好的解决方案。

我想我可以这样做来解决这个问题

for (i in c(1, 2)) {
data <- data %>%
mutate("delta{i}" := delta(paste0('a', i), paste0('b', i), paste0('c', i)))
}

但是我得到了

Error in `mutate()`:
! Problem while computing `delta1 = delta(paste0("a", i), paste0("b", i), paste0("c", i))`.
Caused by error in `a - c`:
! non-numeric argument to binary operator
Run `rlang::last_error()` to see where the error occurred.

,循环遍历突变有点不对。

我已经看到解决方案在变异多/连续列(与dplyr或基础R),我怎么能使用dplyr变异多个变量?或者使用dplyr修改数据帧中的多个列,但是解决方案的可读性要比复制粘贴行并使用副本差得多。

理想情况下,我希望找到一个聪明的使用across,这将允许我写一些像mutate("delta{i}" := delta(a{i}, b{i}, c{i}))

带胶

您可以利用glue函数。这可能是最好的和最灵活的方式:

library(glue)
cols         <- c("1", "2")
exprs        <- glue("(a{cols} - c{cols}) / ((a{cols} + b{cols}) * c{cols} + a{cols})")
names(exprs) <- glue("delta{cols}")
data |> 
mutate(!!!rlang::parse_exprs(exprs))
# A tibble: 2 × 8
a1    a2    b1    b2    c1    c2 delta1   delta2
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl>  <dbl>    <dbl>
1    32    32    50    12    12    50 0.0197 -0.00806
2    48    20    55    43    10    42 0.0353 -0.00825

各地如果你想用across,你可以使用一堆,像这样:

library(dplyr)
data %>% 
mutate((across(starts_with("a"), .names = "delta{sub('a', '', .col)}") -
across(starts_with("c"))) / 
((across(starts_with("a")) + across(starts_with("b"))) * 
across(starts_with("c")) + across(starts_with("a"))))
# A tibble: 2 × 8
a1    a2    b1    b2    c1    c2 delta1   delta2
<dbl> <dbl> <dbl> <dbl> <dbl> <dbl>  <dbl>    <dbl>
1    32    32    50    12    12    50 0.0197 -0.00806
2    48    20    55    43    10    42 0.0353 -0.00825
由旋转

但是,你可能更应该使用长轴和宽轴:

library(dplyr)
library(tidyr)
data %>% 
mutate(rown = row_number()) %>% 
pivot_longer(-rown,
names_to = c(".value", "number"), 
names_pattern = "([a-z])(\d)") %>% 
group_by(rown) %>% 
mutate(delta = (a - c) / ((a + b) * c + a)) %>% 
pivot_wider(names_from = number, 
values_from = a:delta, 
names_sep = "")
# A tibble: 2 × 9
# Groups:   rown [2]
rown    a1    a2    b1    b2    c1    c2 delta1   delta2
<int> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>  <dbl>    <dbl>
1     1    32    32    50    12    12    50 0.0197 -0.00806
2     2    48    20    55    43    10    42 0.0353 -0.00825

最新更新