Reputation: 21
I have many columns for which i want to calculate value based on function (1 + x) ^ k, where x is a value from a particular column and k is index of column for which we try to calculate. I want to calculate this only for a subset of all the columns of the table.
For axample:
df = data.frame(A = c(0.1, 0.05, 0.2), B = c(1, 1, 1), C = c(NA, NA, NA), D = c(NA, NA, NA)
I want to apply the function only to columns C and D, using values from column A.
For example df[1,4] would be calculated as (1 + (-0.1)^4 because 4 is index of column D.
An alternative interpretation is that for the selected columns (C and D in this example), the value is value from previous column multiplied by (1+x), i.e. df[1,4] = df[1,3] * (1 + (-0.1)), giving the same result
Upvotes: 2
Views: 72
Reputation: 886948
An option in base R
would be
df[3:4] <- (1 + df$A)^col(df)[, 3:4]
Or with Reduce
df[c('C', 'D')] <- lapply(match(c('C', 'D'), names(df)), function(i)
Reduce(function(x, y) (1 + y)^i, df[, 'A'],
accumulate = TRUE, init = df$A[1])[-1])
df
# A B C D
#1 0.10 1 1.331000 1.464100
#2 0.05 1 1.157625 1.215506
#3 0.20 1 1.728000 2.073600
Or using map/accumulate
library(purrr)
library(dplyr)
map_dfc(set_names(match(c('C', 'D'), names(df)), names(df)[3:4]), ~ {
i <- .x
accumulate(df$A, ~(1 + .y)^i,
.init = first(df$A))[-1]}) %>%
bind_cols(df[1:2], .)
# A B C D
#1 0.10 1 1.331000 1.464100
#2 0.05 1 1.157625 1.215506
#3 0.20 1 1.728000 2.073600
Upvotes: 0
Reputation: 39858
One dplyr
option could be:
df %>%
rowwise() %>%
mutate((1 + A)^(across(C:D, ~ replace(., is.na(.), 1)) * which(names(.) %in% c("C", "D"))))
A B C D
<dbl> <dbl> <dbl> <dbl>
1 0.1 1 1.33 1.46
2 0.05 1 1.16 1.22
3 0.2 1 1.73 2.07
Or if the C and D columns are always NAs:
df %>%
rowwise() %>%
mutate((1 + A)^(1^across(C:D) * which(names(.) %in% c("C", "D"))))
Upvotes: 1
Reputation: 231
The function you described is defined as follows:
func1 = function(df, i) {
(1+df[1]^i)
}
Upvotes: 0
Reputation: 1564
Maybe something like this:
f = function(df, target_cols = c("C", "D"), index_col = "A"){
# df is your data frame
# target_cols is a vector of columns you want apply the function (1 + x)^k
# index_col is the the x in (1 + x)^k
stopifnot(all(target_cols %in% names(df)))
stopifnot(index_col %in% names(df))
# Get index of target columns i.e k
which_col = which(names(df) %in% target_cols)
# Loop over columns
for(i in which_col){
df[, i] = (1 + df[, index_col])^i
}
return(df)
}
df = data.frame(A = c(0.1, 0.05, 0.2), B = c(1, 1, 1), C = c(NA, NA, NA), D = c(NA, NA, NA))
f(df)
A B C D
1 0.10 1 1.331000 1.464100
2 0.05 1 1.157625 1.215506
3 0.20 1 1.728000 2.073600
Upvotes: 0