Reputation: 209
I am trying this but do not get why I have an error. I tried even to use some formulas like
fA <- EltA~EltA1+EltA2
but I had some errors
geo <- c("AT","BE","CZ","DE")
time <- c(2020, 2020, 2021,2021)
EltA1 <- c(150, NA, 120,NA)
EltA2 <- c(60, 70, 80,NA)
EltA <- c(210,110,200,8200)
test <- data.frame(geo, time, EltA1, EltA2, EltA)
left_side <- "EltA"
right_side <- c("EltA1","EltA2")
test <- test %>%
rowwise() %>%
mutate(right = sum(c_across(any_of(right_side)),na.rm = TRUE)) %>%
ungroup()
test <- test %>%
mutate(across(all_of(right_side),
~ if(is.na(.x) & (right == left_side)) replace_na(.x,0) else .x))
Any clue?
Upvotes: 0
Views: 47
Reputation: 76641
A simple solution.
library(dplyr)
left_side <- "EltA"
right_side <- c("EltA1","EltA2")
test %>%
mutate(right = rowSums(.[c(left_side, right_side)], na.rm = TRUE))
#> geo time EltA1 EltA2 EltA right
#> 1 AT 2020 150 60 210 420
#> 2 BE 2020 NA 70 110 180
#> 3 CZ 2021 120 80 200 400
#> 4 DE 2021 NA NA 8200 8200
Created on 2024-12-06 with reprex v2.1.1
Upvotes: 2
Reputation: 603
The function if is not vectorized and thus you should have the message error "condition of length > 1". To change this, we can use ifelse which is vectorized.
Also, with left_side, I think you want to compare right with column EltA. You can use rlang to do that. I'm not that familiar with rlang, but I used function !! with EltA converted to symbol which seems to do the trick.
Here is my code :
library(tidyverse)
library(rlang)
test <- data.frame(geo, time, EltA1, EltA2, EltA)
left_side <- "EltA"
right_side <- c("EltA1","EltA2")
test <- test %>%
rowwise() %>%
mutate(right = sum(c_across(any_of(c(right_side, left_side))),na.rm = TRUE)) %>%
ungroup()
test %>%
mutate(across(all_of(right_side),
~ ifelse(is.na(.x) & (right == !!sym(left_side)), replace_na(.x,0), .x)))
With the result :
# A tibble: 4 × 6
geo time EltA1 EltA2 EltA right
<chr> <dbl> <dbl> <dbl> <dbl> <dbl>
1 AT 2020 150 60 210 420
2 BE 2020 NA 70 110 180
3 CZ 2021 120 80 200 400
4 DE 2021 0 0 8200 8200
Upvotes: 1
Reputation: 73562
You can try this
> test |>
+ transform(right=rowSums(test[c(left_side, right_side)], na.rm=TRUE)) |>
+ {\(.) {.[.$right == .[left_side], right_side] <- 0; .}}()
geo time EltA1 EltA2 EltA right
1 AT 2020 150 60 210 420
2 BE 2020 NA 70 110 180
3 CZ 2021 120 80 200 400
4 DE 2021 0 0 8200 8200
Upvotes: 2