将函数应用于多个数据框(R)

时间:2013-04-03 15:31:15

标签: r loops dataframe

我有很多数据框,我想要应用相同的功能。

上下文:我有数据框记录主题的时间窗口,指示符为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 ......

5 个答案:

答案 0 :(得分:1)

如果您的功能被调用myfunc,那么要将它应用于对象event1event4,您可以使用

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

<强>解释

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

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

get(x)返回名称等于x

的对象

答案 1 :(得分: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 )

答案 2 :(得分: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}

我通常更喜欢使用“[”版本的“$”,但在这种情况下,我不会发现将它留在后面存在很大的风险。

答案 3 :(得分: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)

答案 4 :(得分:0)

我将首先清理您的示例代码,因为我无法在您的示例上运行而不会出现错误。每当你为某个变量的每个值(“对于每个ID”,在这种情况下)你正在做的事情时,你正在研究一个split-apply-combine问题。我遇到此类问题的首选工具是plyr包,但它不是唯一的。{1}}包。我会把你的程序重写为:

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列表,这些是转换后的版本。