0

我有许多数据框,我想对其应用相同的功能。

上下文:我有记录主题时间窗口的数据框,指示符为 0/1,表示在该时间窗口中是否发生了事件。一个例子:

ID start stop event
1  0     12   0
1  12    24   0 
1  24    36   1
1  36    48   1
2  0     12   0 

等等我有一个函数,它在每个 id 的第一个事件之后删除每个条目,例如,在上面的例子中,ID = 1,开始时间 = 36 的记录。

一个数据集的代码是:(数据集称为 event1 ,IDT 为 ID)

list1 <- which(event1$event == 1)

while(length(list1) >= 1){

  id <- event1[ list1[ 1 ] , ]$IDT
  idplus1 <- event1[ ( list1[1] + 1) , ]$IDT
  b <- which( event1$IDT == id )

  if( id == idplus1 ){ 

     event1 <- event1[- ( ( list1[1] + 1 ) : b[ length(b) ] ) , ]   
   }

 list1 <- list1[-1]  

}

现在,如果我有四个数据集;event1, event2, event3, event4,我想将这个函数应用于每一个,有没有办法定义一个函数来做到这一点?我觉得应该有机会在这里使用 lapply ......

4

5 回答 5

1

如果您的函数被调用myfunc,那么将其应用于event1event4可以使用的对象

lapply(paste0('event',1:4), function(x)  { eventDF <- get(x) ; myfunc(eventDF)   })

说明

paste0('event',1:4)创建要在其上应用函数的对象名称的字符向量。

lapply对上述字符向量的每个元素应用内联函数。

get(x)返回名称等于的对象x

于 2013-04-03T15:50:36.730 回答
1

这是一个如何遍历多个数据帧并在所有数据帧上运行相同系列命令的示例

# list containing multiple data frames
x <- list( mtcars , iris )

# some function you've defined
myfun <-
    function( df ){

        # find numeric variables
        nv <- sapply( df , is.numeric )

        # return the 10th and 90th percentile of each numeric column
        sapply( df[ , nv ] , quantile , c( 0.1 , 0.9 ) )

    }

# run the function across all data frames
lapply( x , myfun )
于 2013-04-03T15:52:40.423 回答
1

未经测试:

evnt.fn <- function(evnt.df)
  list1 <- which(evnt.df$event == 1)
  {while(length(list1) >= 1){
    id <- evnt.df[ list1[ 1 ] , ]$IDT
    idplus1 <- evnt.df[ ( list1[1] + 1) , ]$IDT
    b <- which( evnt.df$IDT == id )
    if( id == idplus1 ){ 
       evnt.df <- evnt.df[- ( ( list1[1] + 1 ) : b[ length(b) ] ) , ]   
     }
   list1 <- list1[-1]  
  } }

lapply(list(event1, event2, event3, event4), evnt.fn)

原理是让它在一个实例上工作,然后把它包装起来:

fnname <- function(instance){substitute "instance" for the data object name}

我通常更喜欢使用 "$" 的 "[[" 版本,但在这种情况下,我认为将它留在里面并没有太大的风险。

于 2013-04-03T15:53:59.247 回答
1

以下是我将如何解决您的问题:

创建数据集(数据框列表)

dat1 <- read.table(text="ID start stop event
1  0     12   0
1  12    24   0 
1  24    36   1
1  36    48   1
2  12    24   0 
2  24    36   1
2  36    48   1
3  0     12   0", header=TRUE)

dat2 <- dat3 <- dat1
dats <- list(dat1, dat2, dat3)

将函数应用于数据框列表

#Function to select up to first 1
FUN <- function(x) {
    splitx <- split(x, x$ID)
    out <- do.call(rbind, lapply(splitx, function(x) {
        inds <- c(which(x$event == 0), which(x$event == 1)[1])
        na.omit(x[inds, ])
    }))
    data.frame(out, row.names=NULL)
}

#apply it to all in list
lapply(dats, FUN)
于 2013-04-03T15:55:55.870 回答
0

我将从清理您的示例代码开始,因为在您的示例中我无法让它在没有错误的情况下运行。每当您对某个变量的每个值(在本例中为“每个 ID”)执行某些操作时,您就会看到拆分-应用-组合问题。对于此类问题,我首选的工具是plyr包,但它不是唯一的。我会将您的程序重写为:

library("plyr")
ddply(event1, .(ID), function(DF) {
  firstevent <- which(DF$event == 1)[1]
  DF[seq(length=firstevent),]
})

这需要event1,按 的唯一值将其拆分ID,并且对于其中的每一个,仅保留第一个事件之前的记录。

这可以很容易地包装在一个函数中。

truncevent <- function(event1) {
  ddply(event1, .(ID), function(DF) {
    firstevent <- which(DF$event == 1)[1]
    DF[seq(length=firstevent),]
  })
}

扩展event1

event1 <- read.table(text=
"ID start stop event
1  0     12   0
1  12    24   0 
1  24    36   1
1  36    48   1
2  0     12   0
2  12    24   1
2  24    36   1", header=TRUE)

我们得到

> truncevent(event1)
  ID start stop event
1  1     0   12     0
2  1    12   24     0
3  1    24   36     1
4  2     0   12     0
5  2    12   24     1

现在我们讨论您关于迭代多个数据集的问题。一种方法是创建一个数据集名称向量,对其进行迭代,然后在其中的每一个上运行函数。

events <- c("event1", "event2", "event3", "event4")
lapply(events, function(event) {
  truncevent(get(event))
})

更自然的是将事件本身放入一个列表中,而不必分别跟踪每个名称。然后迭代这个列表就更简单了。

events <- list(event1, event2, event3, event4)
lapply(events, truncevent)

这两种方法都会给你一个 data.frames 列表,它们是转换后的版本。

于 2013-04-03T15:59:01.810 回答