处理R中的重复任务

时间:2011-05-12 02:15:17

标签: r for-loop dataframe

我经常发现自己不得不在R中执行重复性任务。不得不一遍又一遍地在一个或多个数据结构上运行相同的函数,这非常令人沮丧。

例如,假设我在R中有三个独立的数据帧,我想删除每个数据帧中具有缺失值的行。有三个数据帧,在每个df上运行na.omit()并不是那么困难,但它可能会变得非常低效 当有一百个相似的数据结构需要相同的动作时。

df1 <- data.frame(Region=c("Asia","Africa","Europe","N.America","S.America",NA),
             variable=c(2004,2004,2004,2004,2004,2004), value=c(35,20,20,50,30,NA))

df2 <- data.frame(Region=c("Asia","Africa","Europe","N.America","S.America",NA),
            variable=c(2005,2005,2005,2005,2005,2005), value=c(55,350,40,90,99,NA))

df3 <- data.frame(Region=c("Asia","Africa","Europe","N.America","S.America",NA),
           variable=c(2006,2006,2006,2006,2006,2006), value=c(300,200,200,500,300,NA))

tot04 <- na.omit(df1)
tot05 <- na.omit(df2)
tot06 <- na.omit(df3)

在R中处理重复性任务的一般指导原则是什么?

是的,我认识到这个问题的答案特定于人们面临的任务,但我只是询问用户在重复任务时应该考虑的一般事项。

3 个答案:

答案 0 :(得分:20)

作为一般准则,如果您要将多个对象应用于相同的操作,则应将它们收集到一个数据结构中。然后你可以使用循环,[sl] apply等来一次完成操作。在这种情况下,您可以将它们放入数据框列表中,然后在所有数据框上运行df1,而不是使用单独的数据框df2na.omit等。

dflist <- list(df1, df2, <...>)
dflist <- lapply(dflist, na.omit)

答案 1 :(得分:3)

除了@Hong Ooi回答我建议查看包 plyr 重塑。在您的情况下,以下可能有用:

df1$name <- "var1"
df2$name <- "var2" 
df3$name <- "var3"
df <- rbind(df1,df2,df3)
df <- na.omit(df)

##Get various means:
> ddply(df,~name,summarise,AvgName=mean(value))
  name AvgName
  1 var1    31.0
  2 var2   126.8
  3 var3   300.0

> ddply(df,~Region,summarise,AvgRegion=mean(value)) 
     Region AvgRegion
1    Africa 190.00000
2      Asia 130.00000
3    Europe  86.66667
4 N.America 213.33333
5 S.America 143.00000


> ddply(df,~variable,summarise,AvgVar=mean(value))
  variable AvgVar
1     2004   31.0
2     2005  126.8
3     2006  300.0

##Transform the data.frame into another format   
> cast(Region+variable~name,data=df)
      Region variable var1 var2 var3
1     Africa     2004   20   NA   NA
2     Africa     2005   NA  350   NA
3     Africa     2006   NA   NA  200
4       Asia     2004   35   NA   NA
5       Asia     2005   NA   55   NA
6       Asia     2006   NA   NA  300
7     Europe     2004   20   NA   NA
8     Europe     2005   NA   40   NA
9     Europe     2006   NA   NA  200
10 N.America     2004   50   NA   NA
11 N.America     2005   NA   90   NA
12 N.America     2006   NA   NA  500
13 S.America     2004   30   NA   NA
14 S.America     2005   NA   99   NA
15 S.America     2006   NA   NA  300

答案 2 :(得分:3)

如果名称相似,您可以使用pattern ls参数迭代它们:

for (i in ls(pattern="df")){
  assign(paste("t",i,sep=""),na.omit(get(i)))
}

然而,更“R”的做法似乎是使用单独的环境和eapply

# setup environment
env <- new.env()

# copy dataframes across (using common pattern)
for (i in ls(pattern="df")){
  asssign(i,get(i),envir=env)
  }

# apply function on environment
eapply(env,na.omit)

哪个收益率:

$df3
     Region variable value
1      Asia     2006   300
2    Africa     2006   200
3    Europe     2006   200
4 N.America     2006   500
5 S.America     2006   300

$df2
     Region variable value
1      Asia     2005    55
2    Africa     2005   350
3    Europe     2005    40
4 N.America     2005    90
5 S.America     2005    99

$df1
     Region variable value
1      Asia     2004    35
2    Africa     2004    20
3    Europe     2004    20
4 N.America     2004    50
5 S.America     2004    30

不幸的是,这是一个巨大的列表,因此将其作为单独的对象来解决这个问题有点棘手。有点像:

lapply(eapply(env,na.omit),function(x) assign(paste("t",substitute(x),sep=""),x,envir=.GlobalEnv))

应该有效,但substitute没有正确选择列表元素名称。