Alexander
Alexander

Reputation: 4645

conditional Substacting numbers

I have data frame like this

test <- data.frame(gr=rep(letters[1:2],each=6),No=c(100:105,200:205))

   gr  No
1   a 100
2   a 101
3   a 102
4   a 103
5   a 104
6   a 105
7   b 200
8   b 201
9   b 202
10  b 203
11  b 204
12  b 205

in the No column the numbers are increasing in each gr. I need to sum gr a with 100 and b with 50 and need to have consecutive decrease after this operation.

I would like to have a new column that consecutive decrease with this increase. So I tried

decrese_func <- function(No,gr){

   if(any(gr=="a")){
     No+100

   }
   else
    No+50 
 }

   test%>%
   group_by(gr)%>%
   mutate(new_column=decrese_func(No,gr))

# A tibble: 12 x 3
# Groups:   gr [2]
   gr       No new_column
   <fct> <int>      <dbl>
 1 a       100        200
 2 a       101        201
 3 a       102        202
 4 a       103        203
 5 a       104        204
 6 a       105        205
 7 b       200        250
 8 b       201        251
 9 b       202        252
10 b       203        253
11 b       204        254
12 b       205        255

but what I need is like this

 gr       No new_column
   <fct> <int>      <dbl>
 1 a       100        200
 2 a       101        199
 3 a       102        198
 4 a       103        197
 5 a       104        196
 6 a       105        195
 7 b       200        250
 8 b       201        249
 9 b       202        248
10 b       203        247
11 b       204        246
12 b       205        245

I cannot figure it out how to have consecutive decrease ?

Thx.

Upvotes: 0

Views: 45

Answers (2)

akrun
akrun

Reputation: 887691

Here is a way to do this in base R

test$New <- with(test, No + c(100, 50)[cumsum(!duplicated(gr))] - 2*(No %% 100))
test$New
#[1] 200 199 198 197 196 195 250 249 248 247 246 245

Or a slight variation with match

with(test, No + c(100, 50)[match(gr, unique(gr))] - 2*(No %% 100))

Upvotes: 1

tyluRp
tyluRp

Reputation: 4768

Not the most elegant answer but in the mean time, this may work:

library(dplyr)

test %>% 
  mutate(A = case_when(gr == "a" ~ 100,
                       gr == "b" ~ 50,
                       TRUE ~ NA_real_)) %>% 
  group_by(gr) %>% 
  mutate(B = (1:NROW(gr) - 1) * 2,
         New_Column = No + A - B)
# A tibble: 12 x 5
# Groups:   gr [2]
   gr       No     A     B New_Column
   <fct> <int> <dbl> <dbl>      <dbl>
 1 a       100   100     0        200
 2 a       101   100     2        199
 3 a       102   100     4        198
 4 a       103   100     6        197
 5 a       104   100     8        196
 6 a       105   100    10        195
 7 b       200    50     0        250
 8 b       201    50     2        249
 9 b       202    50     4        248
10 b       203    50     6        247
11 b       204    50     8        246
12 b       205    50    10        245

Add select(gr, No, New_Column) at the end of the chain to get gr, No and New_Column only. I left the other columns just to show what's going on.

And if you want to wrap it into a function you could do something like:

desc_func <- function(group_var, condition, if_true_add, if_false_add, to_number) {
  ifelse(
    group_var == condition, 
    to_number + if_true_add - (1:NROW(group_var) - 1) * 2, 
    to_number + if_false_add - (1:NROW(group_var) - 1) * 2)
}

test %>% 
  group_by(gr) %>% 
  mutate(test_var = desc_func(gr, "a", 100, 50, No))
# A tibble: 12 x 3
# Groups:   gr [2]
   gr       No test_var
   <fct> <int>    <dbl>
 1 a       100      200
 2 a       101      199
 3 a       102      198
 4 a       103      197
 5 a       104      196
 6 a       105      195
 7 b       200      250
 8 b       201      249
 9 b       202      248
10 b       203      247
11 b       204      246
12 b       205      245

Upvotes: 1

Related Questions