Home > Net >  How to automate custom function to multiple rows?
How to automate custom function to multiple rows?

Time:12-23

I have created a function like the following

DI <- function(W=W, V=V, Ci=Ci, Cf=Cf, Cf_Des=Cf_Des, Vres=Vres, 
               Vfinal=Vfinal, onebyn_ads=onebyn_ads) {
  Ads <- (Ci - Cf)*(V/W)
  Cf_D1 <- Cf_Des[[1]]
  Ci_D1 <- max(Cf, na.rm=T)/(Vfinal/Vres)
  Des1 <- (Cf_D1 - Ci_D1)*(Vfinal/W)  
  Ads_D1 <- max(Ads, na.rm=T) - Des1
  Cf_D2 <- Cf_Des[[2]]
  Ci_D2 <- Cf_D1/(Vfinal/Vres)
  Des2 <- (Cf_D2 - Ci_D2)*(Vfinal/W)
  Ads_D2 <- Ads_D1 - Des2
  Cf_D3 <- Cf_Des[[3]]
  Ci_D3 <- Cf_D2/(Vfinal/Vres)
  Des3 <- (Cf_D3 - Ci_D3)*(Vfinal/W)
  Ads_D3 <-  Ads_D2 - Des3
  Cf_D4 <- Cf_Des[[4]]
  Ci_D4 <- Cf_D3/(Vfinal/Vres)
  Des4 <- (Cf_D4 - Ci_D4)*(Vfinal/W)
  Ads_D4 <- Ads_D3 - Des4  
  Ads_Des <- c(Ads_D1, Ads_D2, Ads_D3, Ads_D4)
  log_Cf_Des <- log10(Cf_Des)
  log_Ads_Des <- log10(Ads_Des)
  fit.slr <- lm(log_Ads_Des ~ log_Cf_Des)
  a <- 10^coef(fit.slr)[[1]]
  onebyn <- coef(fit.slr)[[2]]
  DI <- onebyn_ads/onebyn
  return(list(a=a, onebyn=onebyn, DI=DI))
}

The function is running fine for a dataset having 4 rows like

DI(W=2, V=20, Ci=df$Initial_conc, Cf=df$Equilibrium_conc, 
   Cf_Des=df$Cf_Des, Vres= 5, Vfinal=20, onebyn_ads=0.2056263)

Now you can see in the function that from Cf_D1 to Cf_D4, rowwise subsetting of Cf_Des is done upto 4th row. Suppose someone is having more than 4 rows in their data, then it will not calculate correctly. How can I make it run for any number of rows of data? Here is the example data

df <- structure(list(Initial_conc = c(10, 20, 40, 60), Equilibrium_conc = c(0.61958938580799, 
1.63333333333333, 17.27814490161, 35.1896333333333), Cf_Des = c(13.6284722222222, 
7.47767857142857, 6.0515873015873, 4.83630952380952)), row.names = c(NA, 
4L), class = "data.frame")

CodePudding user response:

Obviously the calculation is initialized on Cf_D1. After doing this, use a for loop of 2 to NROW iterations.

DI2 <- function(W=W, V=V, Ci=Ci, Cf=Cf, Cf_Des=Cf_Des, Vres=Vres, 
                Vfinal=Vfinal, onebyn_ads=onebyn_ads) {
  ## ini
  Ads <- (Ci - Cf)*(V/W)
  Ads_Des <- numeric(length(Cf_Des))
  Ci_x <- max(Cf, na.rm=T)/(Vfinal/Vres)
  Ads_Des[[1]] <- Ads_x <- max(Ads, na.rm=T) - (Cf_Des[[1]] - Ci_x)*(Vfinal/W)
  ## loop
  for (i in seq_along(Cf_Des)[-1]) {
    Des_x <- (Cf_Des[[i]] - Cf_Des[[i - 1]]/(Vfinal/Vres))*(Vfinal/W)
    Ads_Des[[i]] <- Ads_x <- Ads_x - Des_x
  }
  ## processing
  log_Cf_Des <- log10(Cf_Des)
  log_Ads_Des <- log10(Ads_Des)
  fit.slr <- lm(log_Ads_Des ~ log_Cf_Des)
  a <- 10^coef(fit.slr)[[1]]
  onebyn <- coef(fit.slr)[[2]]
  DI <- onebyn_ads/onebyn
  return(list(a=a, onebyn=onebyn, DI=DI))
}

with(df, DI2(W=2, V=20, Ci=Initial_conc, Cf=Equilibrium_conc, 
   Cf_Des=Cf_Des, Vres= 5, Vfinal=20, onebyn_ads=0.2056263))
# $a
# [1] 27.26784
# 
# $onebyn
# [1] 0.7923875
# 
# $DI
# [1] 0.2595022

The results of DI and DI2 are equal for original data frame df:

stopifnot(all.equal(with(df, DI(W=2, V=20, Ci=Initial_conc, Cf=Equilibrium_conc, 
                       Cf_Des=Cf_Des, Vres= 5, Vfinal=20, onebyn_ads=0.2056263)), 
          with(df, DI2(W=2, V=20, Ci=Initial_conc, Cf=Equilibrium_conc, 
                       Cf_Des=Cf_Des, Vres= 5, Vfinal=20, onebyn_ads=0.2056263))
          ))

Now using arbitrary number of rows in df2:

with(df2, DI2(W=2, V=20, Ci=Initial_conc, Cf=Equilibrium_conc, 
             Cf_Des=Cf_Des, Vres= 5, Vfinal=20, onebyn_ads=0.2056263))
# $a
# [1] 178.621
# 
# $onebyn
# [1] 0.3131333
# 
# $DI
# [1] 0.6566735

Note, that by using with you can avoid specifying df$ when calling the funtion.


Data:

df <- structure(list(Initial_conc = c(10, 20, 40, 60), Equilibrium_conc = c(0.61958938580799, 
1.63333333333333, 17.27814490161, 35.1896333333333), Cf_Des = c(13.6284722222222, 
7.47767857142857, 6.0515873015873, 4.83630952380952)), row.names = c(NA, 
4L), class = "data.frame")

df2 <- structure(list(Initial_conc = c(10L, 20L, 40L, 60L, 80L, 100L, 
120L), Equilibrium_conc = c(0.6195894, 1.6333333, 17.2781449, 
35.1896333, 55.1896333, 85.1896333, 115.1896333), Cf_Des = c(13.628472, 
7.477679, 6.051587, 4.83631, 3.83631, 2.83631, 1.83631)), class = "data.frame", row.names = c("1", 
"2", "3", "4", "5", "6", "7"))

CodePudding user response:

You could include a loop in your function:

DI <- function(W=W, V=V, Ci=Ci, Cf=Cf, Cf_Des=Cf_Des, Vres=Vres, Vfinal=Vfinal, onebyn_ads=onebyn_ads) {
Ads <- (Ci - Cf)*(V/W)
Ads_Des <- c()
for (k in 1:length(Cf)){

  Cf_D1 <- Cf_Des[[k]]
  Ci_D1 <- max(Cf, na.rm=T)/(Vfinal/Vres)
  Des1 <- (Cf_D1 - Ci_D1)*(Vfinal/W)  
  Ads_D1 <- max(Ads, na.rm=T) - Des1
  Ads_Des <- append(Ads_Des, Ads_D1)
}

log_Cf_Des <- log10(Cf_Des)
log_Ads_Des <- log10(Ads_Des)
fit.slr <- lm(log_Ads_Des ~ log_Cf_Des)
a <- 10^coef(fit.slr)[[1]]
onebyn <- coef(fit.slr)[[2]]
DI <- onebyn_ads/onebyn
return(list(a=a, onebyn=onebyn, DI=DI))
}

Example with 5 rows:

df <- structure(list(Initial_conc = c(10, 20, 40, 60, 70), 
                 Equilibrium_conc = c(0.61958938580799,  1.63333333333333, 17.27814490161, 35.1896333333333, 40.5), 
                 Cf_Des = c(13.6284722222222, 7.47767857142857, 6.0515873015873, 4.83630952380952, 9.78)), row.names = c(NA, 5L), class = "data.frame")

Call your function:

DI(W=2, V=20, Ci=df$Initial_conc, Cf=df$Equilibrium_conc, Cf_Des=df$Cf_Des, Vres= 5, Vfinal=20, onebyn_ads=0.2056263)
  • Related