IRT
IRT

Reputation: 209

across dimension computation

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

Answers (3)

Rui Barradas
Rui Barradas

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

Guillaume Mulier
Guillaume Mulier

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

jay.sf
jay.sf

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

Related Questions