Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding a variable to tidy data whose value is based on a column-row calculation

Tags:

r

My current project contains data that's got a structure like:

my_df <- tibble(
  zn = c("hm","hm", "hm", "h60","h60","h60", "h85","h85","h85"),
  nm = c("c", "cA", "cB", "c","cA", "cB", "c","cA", "cB"), 
  val = c(60, 40, 20, 250, 150, 100, 400, 250, 150),
  znt = c(100, 100, 100, 300, 300, 300, 500, 500, 500), 
)

my_df
# A tibble: 9 x 4
zn    nm      val   znt
  <chr> <chr> <dbl> <dbl>
1 hm    c        60   100
2 hm    cA       40   100
3 hm    cB       20   100
4 h60   c       250   300
5 h60   cA      150   300
6 h60   cB      100   300
7 h85   c       400   500
8 h85   cA      250   500
9 h85   cB      150   500

And I would like to add a new variable, c0, whose value is defined c0 = znt - c for each zn. The final result would look like:

# A tibble: 12 x 4
   zn    nm      val   znt
   <chr> <chr> <dbl> <dbl>
 1 hm    c0       40   100
 2 hm    c        60   100
 3 hm    cA       40   100
 4 hm    cB       20   100
 5 h60   c0       50   300
 6 h60   c       250   300
 7 h60   cA      150   300
 8 h60   cB      100   300
 9 h85   c0      100   500
10 h85   c       400   500
11 h85   cA      250   500
12 h85   cB      150   500

I have an idea about how to do it but it seems very convoluted and I'm hoping there's a better way. If this could be accomplished using something from the tidyverse that'd be awesome, too.

like image 460
jmb277 Avatar asked Aug 08 '26 09:08

jmb277


2 Answers

Another option:

library(tidyverse)

my_df %>%
  group_split(zn) %>%
  map_dfr(~ add_row(.data = ., 
                    zn = .$zn[1], 
                    nm = 'c0', 
                    val = .$znt[1] - .$val[.$nm == 'c'], 
                    znt = .$znt[1],
                    .before = 1))

Output:

# A tibble: 12 x 4
   zn    nm      val   znt
 * <chr> <chr> <dbl> <dbl>
 1 h60   c0       50   300
 2 h60   c       250   300
 3 h60   cA      150   300
 4 h60   cB      100   300
 5 h85   c0      100   500
 6 h85   c       400   500
 7 h85   cA      250   500
 8 h85   cB      150   500
 9 hm    c0       40   100
10 hm    c        60   100
11 hm    cA       40   100
12 hm    cB       20   100
like image 183
arg0naut91 Avatar answered Aug 11 '26 00:08

arg0naut91


my_df %>% 
   bind_rows(my_df %>% filter(nm == "c") %>% 
   mutate(nm = "c0" ,  val = znt - val)) %>% 
   arrange(zn, nm)

gives

zn    nm      val   znt
   <chr> <chr> <dbl> <dbl>
 1 h60   c       250   300
 2 h60   c0       50   300
 3 h60   cA      150   300
 4 h60   cB      100   300
 5 h85   c       400   500
 6 h85   c0      100   500
 7 h85   cA      250   500
 8 h85   cB      150   500
 9 hm    c        60   100
10 hm    c0       40   100
11 hm    cA       40   100
12 hm    cB       20   100
like image 25
Annet Avatar answered Aug 10 '26 22:08

Annet