Работа с повторяющимися задачами в R
Я часто сталкиваюсь с необходимостью выполнять повторяющиеся задачи в R. Крайне сложно расходовать постоянную работу одной и той же функции на одной или нескольких структурах данных снова и снова.
Например, скажем, у меня есть три отдельных кадра данных в R, и я хочу удалить строки в каждом кадре данных, которые обладают отсутствующим значением. С тремя кадрами данных не все, что трудно запускать na.omit() на каждом из df, но оно может стать крайне неэффективным
когда имеется одна сотня похожих структур данных, которые требуют того же действия.
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?
Да, я понимаю, что ответ на этот вопрос специфичен для задачи, с которой вы сталкиваетесь, но я просто спрашиваю об общих вещах, которые должен учитывать пользователь, когда у них есть повторяющаяся задача.
Ответы
Ответ 1
В качестве общего руководства, если у вас есть несколько объектов, к которым вы хотите применить одни и те же операции, вы должны собрать их в одну структуру данных. Затем вы можете использовать циклы, [sl] apply и т.д., Чтобы выполнять операции за один раз. В этом случае вместо отдельных кадров данных df1
, df2
и т.д. Вы можете поместить их в список фреймов данных и затем запустить na.omit
для всех из них:
dflist <- list(df1, df2, <...>)
dflist <- lapply(dflist, na.omit)
Ответ 2
Кроме ответа @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
Ответ 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
не правильно выбирает имена элементов списка.