Decremental multiplication in R
Below is a sample data df
, with many variables, where C
is one, the length of a column in a variable.
ID C
1 0
2 1.47349678
3 0
4 0
5 0
6 0
7 0
8 0
9 0
10 0
11 0
12 0
13 0
14 0
16 1.987
17 0
18 0
19 0
20 0
21 0
22 0
23 0
24 0
25 0
26 0
27 0
I need to create another variable C_C
where it consists of a product C
and a decremental factor by 0.1 .
Multiplication should only be done to count 10
values C_C
from a point where there is a value C
other than 0
. Also the result must be saved from the next data point. If C !=0
is in Id ==2
, then the product should be kept from. ID==3
If the number is less than 10
continuous zeros after a nonzero number will only be reset to a new value C
, and if no further data is found, multiplication will stop.
Expected Result
ID C C_C
1 0 0
2 1.47349678 0
3 0 1.47349678
4 0 1.326147102
5 0 1.178797424
6 0 1.031447746
7 0 0.884098068
8 0 0.73674839
9 0 0.589398712
10 0 0.442049034
11 0 0.294699356
12 0 0.147349678
13 0 0
14 0 0
16 1.987 0
17 0 1.987
18 0 1.7883
19 0 1.5896
20 0 1.3909
21 0 1.1922
22 0 0.9935
23 0 0.7948
24 0 0.5961
25 0 0.3974
26 0 0.1987
27 0 0
Observing the required result
1. The value in C
, which is not 0
, is enocunter in ID = 2
, therefore the product is kept from ID == 3
ie C_C3
.
2. C_C3 == C2 * 1
, C_C4 == C2*0.9
, C_C5 == C2 * 0.8
...... C_C12 == C*0.1
, C_C13 == C2 *0
.
3. Similarly C_C17 == C16 * 1
, C_C18 == C16*0.9
, C_C19 == C16 *0.8
, .... C_C26 == C16 *0.1
,C_C27 == C16*0
Thank!
source to share
With dplyr:
library(dplyr)
df$group = cumsum(dt$C>0)
df = df %>% group_by(group) %>% mutate(value=sum(C)) %>%
mutate(n=1.1-0.1*(row_number()-1)) %>% mutate(n=ifelse(n<0|value==0|n==1.1,0,n)) %>%
mutate(C_C = n*value) %>% ungroup() %>% select(-n,-group,-value) %>% as.data.frame()
ID C C_C
1 1 0.000 0.0000
2 2 1.473 0.0000
3 3 0.000 1.4735
4 4 0.000 1.3261
5 5 0.000 1.1788
6 6 0.000 1.0314
7 7 0.000 0.8841
8 8 0.000 0.7367
9 9 0.000 0.5894
10 10 0.000 0.4420
11 11 0.000 0.2947
12 12 0.000 0.1473
13 13 0.000 0.0000
14 14 0.000 0.0000
15 16 1.987 0.0000
16 17 0.000 1.9870
17 18 0.000 1.7883
18 19 0.000 1.5896
19 20 0.000 1.3909
20 21 0.000 1.1922
21 22 0.000 0.9935
22 23 0.000 0.7948
23 24 0.000 0.5961
24 25 0.000 0.3974
25 26 0.000 0.1987
26 27 0.000 0.0000
source to share
Slightly lengthy procedure sapply
from the R base
vals <- which(df$C != 0)
values <- c(sapply(df$C[vals], function(x) x * rev(seq(0.1, 1.0, 0.1))))
inds <- c(sapply(vals + 1, function(x) seq(x, x+9)))
df$C_C <- 0
df$C_C[inds] <- values
df$C_C
# [1] 0.0000000 0.0000000 1.4734968 1.3261471 1.1787974 1.0314477 0.8840981
# [8] 0.7367484 0.5893987 0.4420490 0.2946994 0.1473497 0.0000000 0.0000000
#[15] 0.0000000 1.9870000 1.7883000 1.5896000 1.3909000 1.1922000 0.9935000
#[22] 0.7948000 0.5961000 0.3974000 0.1987000 0.0000000
Here we first find indices that are not equal to 0 ( vals
), get their corresponding values ( df$C[vals]
), and for each value, we multiply it by 1.0, 0.9, 0.8 ... etc, Now that we have everything values
we need, now to place these values
we will generate its corresponding indices ( inds
) using a function seq
. Now we can just assign values
at their respective indices ( inds
) and assign 0 to the remaining values.
source to share