Подтвердить что ты не робот

Работа с повторяющимися задачами в 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?

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

4b9b3361

Ответ 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 не правильно выбирает имена элементов списка.