Работа с повторяющимися задачами в R - PullRequest
17 голосов
/ 12 мая 2011

Я часто сталкиваюсь с необходимостью выполнять повторяющиеся задачи в 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?

Да, я понимаю, что ответ на этот вопрос специфичен для задачи, с которой он сталкивается, но я просто спрашиваю об общих вещах, которые пользователь должен учитывать, когда у него повторяющаяся задача.

Ответы [ 3 ]

20 голосов
/ 12 мая 2011

В качестве общего руководства, если у вас есть несколько объектов, к которым вы хотите применить одни и те же операции, вы должны собрать их в одну структуру данных. Затем вы можете использовать циклы, [sl] apply и т. Д. Для выполнения операций за один раз. В этом случае вместо отдельных фреймов данных df1, df2 и т. Д. Вы можете поместить их в список фреймов данных, а затем запустить na.omit для всех из них:

dflist <- list(df1, df2, <...>)
dflist <- lapply(dflist, na.omit)
3 голосов
/ 12 мая 2011

Если имена похожи, вы можете перебрать их, используя аргумент pattern для ls:

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

Однако, более «R» способ сделать это, похоже, использовать отдельныйenvironment и 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 неправильно выбирает имена элементов списка.

3 голосов
/ 12 мая 2011

Кроме ответа @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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...