如何让自定义R函数适配任意行数的数据集?
修改R函数DI以支持任意行数的数据集
原函数及问题描述
原DI函数代码如下:
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)) }
该函数仅能处理长度为4的Cf_Des向量,因为代码中硬编码了Cf_D1到Cf_D4的索引,当Cf_Des长度超过或不足4时,函数会报错或计算错误。
调用示例(基于4行数据集):
# 示例数据集 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") # 调用原函数 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)
修改后的函数
将硬编码的步骤替换为循环计算,以下是修改后的版本:
DI <- function(W, V, Ci, Cf, Cf_Des, Vres, Vfinal, onebyn_ads) { # 计算初始吸附量 Ads <- (Ci - Cf) * (V / W) max_Ads <- max(Ads, na.rm = TRUE) dilution_factor <- Vfinal / Vres # 初始化变量 n <- length(Cf_Des) Ads_Des <- numeric(n) prev_Cf <- max(Cf, na.rm = TRUE) # 初始Ci_D1对应的Cf值 # 循环计算每一步的Ads_Des for (i in 1:n) { current_Cf_Des <- Cf_Des[i] Ci_D <- prev_Cf / dilution_factor Des <- (current_Cf_Des - Ci_D) * (Vfinal / W) Ads_Des[i] <- if (i == 1) max_Ads - Des else Ads_Des[i-1] - Des # 更新prev_Cf为当前的Cf_Des,用于下一次循环 prev_Cf <- current_Cf_Des } # 拟合线性模型并计算结果 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_value <- onebyn_ads / onebyn return(list(a = a, onebyn = onebyn, DI = DI_value)) }
修改说明
- 移除硬编码的
Cf_D1到Cf_D4,改用循环遍历Cf_Des的所有元素,支持任意长度的输入 - 引入
dilution_factor变量存储Vfinal/Vres,避免重复计算 - 用
prev_Cf变量跟踪上一步的Cf_Des值,用于计算当前的Ci_D - 初始化
Ads_Des为对应长度的数值向量,循环填充每一个元素 - 保留原函数的核心计算逻辑和返回结果结构
测试验证
使用示例数据集调用修改后的函数,结果与原函数一致:
# 调用修改后的函数 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)
你也可以测试更长的Cf_Des向量(比如扩展数据集到5行),函数会自动处理所有元素。
内容的提问来源于stack exchange,提问作者UseR10085
相关产品推荐
相关产品推荐

