我经常发现自己不得不在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中处理重复性任务的一般指导原则是什么?
是的,我认识到这个问题的答案特定于人们面临的任务,但我只是询问用户在重复任务时应该考虑的一般事项。
答案 0 :(得分:20)
作为一般准则,如果您要将多个对象应用于相同的操作,则应将它们收集到一个数据结构中。然后你可以使用循环,[sl] apply等来一次完成操作。在这种情况下,您可以将它们放入数据框列表中,然后在所有数据框上运行df1
,而不是使用单独的数据框df2
,na.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
没有正确选择列表元素名称。