简体   繁体   English

如何为这个 function 申请“lapply”? (右)

[英]How to apply 'lapply' for this function? (R)

I have a function that calculates 'incremental AUC(area under the curve)' when given certain values per time points (0, 15, 30, ... 120min).我有一个 function 在给定每个时间点(0、15、30、... 120 分钟)的某些值时计算“增量 AUC(曲线下面积)”。 I want to apply this function to batch calculate my columns and ideally create a new 'list' that contains only the 'auc' values from each run, but having trouble coding this.我想应用此 function 来批量计算我的列,并理想地创建一个新的“列表”,其中仅包含每次运行的“auc”值,但在编码时遇到问题。 I was thinking 'lapply' may work, but wonder if there are better suggestions since I would be creating similar functions and run them in batch in futures.我在想“lapply”可能有用,但想知道是否有更好的建议,因为我会创建类似的功能并在未来批量运行它们。 Thank you so much guys.十分感谢大家。 Below is the function where the data frame=df1, CAT.12 being one of the columns.下面是 function,其中数据帧=df1,CAT.12 是其中一列。 X is the time while y being the variable (column). X 是时间,而 y 是变量(列)。

i_auc.fn <- function(x,y) {
  auc <- ifelse(y[2] > y[1], (y[2]-y[1])*(x[2]-x[1])/2, 0)
  seg.type <- 0
  for (i in 3:length(x)) {
    if (y[i] >= y[1] & y[i-1] >= y[1]) {
      auc[i-1] <- (((y[i]-y[1])/2) + (y[i-1]-y[1])/2) * (x[i]-x[i-1])/2
      seg.type[i-1] <- 1
    } else if (y[i] >= y[1] & y[i-1] < y[1]) {
      auc[i-1] <- ((y[i]-y[1])^2/(y[i]-y[i-1])) * (x[i]-x[i-1])/2
      seg.type[i-1] <- 2
    } else if (y[i] < y[1] & y[i-1] >= y[1]) {
      auc[i-1] <- ((y[i-1]-y[1])^2/(y[i-1]-y[i])) * (x[i]-x[i-1])/2
      seg.type[i-1] <- 3
    } else if (y[i] < y[1] & y[i-1] < y[1]) {
      auc[i-1] <- 0
      seg.type[i-1] <- 4
    } else {
      # The above cases are exhaustive, so this should never happpen
      return(cat("i:", i, "Error: No condition met\n"))
    }
  }
  return(list(auc=sum(auc), segments=auc, seg.type=seg.type))
}
iAUC <- i_auc.fn(df1$time, df1$CAT.12)

my df1 looks like this我的 df1 看起来像这样

lapply() takes a list and a function as its input arguments to output a result. lapply()将一个列表和一个 function 作为其输入 arguments 到 output 一个结果。 Here, you have a dataframe instead of a list as your input argument.在这里,您有一个 dataframe 而不是列表作为输入参数。 Consequently, you cannot use lapply() with your data as it is.因此,您不能按原样对数据使用lapply() Here are two options I can offer:以下是我可以提供的两种选择:

Option 1: This is not the most elegant solution, admittedly, but it gets you this list output you desire.选项 1:诚然,这不是最优雅的解决方案,但它可以为您提供您想要的 output 列表。 Simply loop through the columns of your dataframe expect for the time column and save each result as a new element of a list.只需循环遍历您的 dataframe 的列期望时间列,并将每个结果保存为列表的新元素。 Here is a reproducible example of that approach:这是该方法的可重现示例:

set.seed(450)

time<-seq(0,120,15)
CAT.01<-rnorm(9, 5, 2)
CAT.02<-rnorm(9, 5, 0.4)
CAT.03<-rnorm(9, 5, 0.22)
CAT.04<-rnorm(9, 5, 1.52)
CAT.05<-rnorm(9, 5, 1.5)
CAT.06<-rnorm(9, 5, 2.1)
CAT.07<-rnorm(9, 5, 3)

LST<-data.frame(time, CAT.01, CAT.02, CAT.03, CAT.04, CAT.05, CAT.06, CAT.07)

i_auc.fn <- function(x,y) {
  auc <- ifelse(y[2] > y[1], (y[2]-y[1])*(x[2]-x[1])/2, 0)
  seg.type <- 0
  for (i in 3:length(x)) {
    if (y[i] >= y[1] & y[i-1] >= y[1]) {
      auc[i-1] <- (((y[i]-y[1])/2) + (y[i-1]-y[1])/2) * (x[i]-x[i-1])/2
      seg.type[i-1] <- 1
    } else if (y[i] >= y[1] & y[i-1] < y[1]) {
      auc[i-1] <- ((y[i]-y[1])^2/(y[i]-y[i-1])) * (x[i]-x[i-1])/2
      seg.type[i-1] <- 2
    } else if (y[i] < y[1] & y[i-1] >= y[1]) {
      auc[i-1] <- ((y[i-1]-y[1])^2/(y[i-1]-y[i])) * (x[i]-x[i-1])/2
      seg.type[i-1] <- 3
    } else if (y[i] < y[1] & y[i-1] < y[1]) {
      auc[i-1] <- 0
      seg.type[i-1] <- 4
    } else {
      # The above cases are exhaustive, so this should never happpen
      return(cat("i:", i, "Error: No condition met\n"))
    }
  }
  return(list(auc=sum(auc), segments=auc, seg.type=seg.type))
}

OUT.LIST<-list()
for(i in 2:ncol(DF)){
  OUT.LIST[[i]]<-i_auc.fn(DF$time, DF[,i])
}

Option 2# Make your input a list first, and then use lapply() .选项 2# 首先将您的输入设为列表,然后使用lapply() Here is a reproducible example of that approach:这是该方法的可重现示例:

set.seed(450)

time<-seq(0,120,15)
CAT.01<-rnorm(9, 5, 2)
CAT.02<-rnorm(9, 5, 0.4)
CAT.03<-rnorm(9, 5, 0.22)
CAT.04<-rnorm(9, 5, 1.52)
CAT.05<-rnorm(9, 5, 1.5)
CAT.06<-rnorm(9, 5, 2.1)
CAT.07<-rnorm(9, 5, 3)

DF<-list(CAT.01, CAT.02, CAT.03, CAT.04, CAT.05, CAT.06, CAT.07)

i_auc.fn <- function(x,y) {
  auc <- ifelse(y[2] > y[1], (y[2]-y[1])*(x[2]-x[1])/2, 0)
  seg.type <- 0
  for (i in 3:length(x)) {
    if (y[i] >= y[1] & y[i-1] >= y[1]) {
      auc[i-1] <- (((y[i]-y[1])/2) + (y[i-1]-y[1])/2) * (x[i]-x[i-1])/2
      seg.type[i-1] <- 1
    } else if (y[i] >= y[1] & y[i-1] < y[1]) {
      auc[i-1] <- ((y[i]-y[1])^2/(y[i]-y[i-1])) * (x[i]-x[i-1])/2
      seg.type[i-1] <- 2
    } else if (y[i] < y[1] & y[i-1] >= y[1]) {
      auc[i-1] <- ((y[i-1]-y[1])^2/(y[i-1]-y[i])) * (x[i]-x[i-1])/2
      seg.type[i-1] <- 3
    } else if (y[i] < y[1] & y[i-1] < y[1]) {
      auc[i-1] <- 0
      seg.type[i-1] <- 4
    } else {
      # The above cases are exhaustive, so this should never happpen
      return(cat("i:", i, "Error: No condition met\n"))
    }
  }
  return(list(auc=sum(auc), segments=auc, seg.type=seg.type))
}

OUT.LIST<-lapply(LST, i_auc.fn, time)

There maybe an approach with using the dlply() and colwise() functions in the plyr:: package, but because you aren't splitting your data along the time series, the result is simply a one list element.plyr:: package 中可能有一种使用dlply()colwise()函数的方法,但是由于您没有沿时间序列拆分数据,因此结果只是一个列表元素。 Someone else may be able to find a way to make that work.其他人也许能够找到一种方法来完成这项工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM