Работа с повторяющимися задачами в R

17

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

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

задан ATMathew 12.05.2011 в 04:15
источник

3 ответа

20

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

dflist <- list(df1, df2, <...>)
dflist <- lapply(dflist, na.omit)
    
ответ дан Hong Ooi 12.05.2011 в 04:21
источник
  • Недостатком этого является следующее: когда операция не выполняется на последнем из ваших данных, вы теряете все свои результаты (или кто-нибудь знает способ получения тех, которые не сбой)? Он также может страдать от проблем с ресурсами (память!) (Хотя их может быть трудно избежать без предложения @Hong Ooi). По моему опыту, он помогает использовать редактор вне R (например, Tinn-R или новый RStudio). –  Nick Sabbe 12.05.2011 в 09:18
  • @Nick: вы можете использовать tryCatch для устранения сбоев в работе. Сделайте это отдельным вопросом, если вы хотите получить более полный ответ. –  Richie Cotton 12.05.2011 в 09:26
  • Кто-нибудь НЕ использует IDE ?! Я не могу представить жизнь без нее. –  Roman Luštrik 12.05.2011 в 09:31
  • @ Ричи: Нет, спасибо. Я знаю о tryCatch (хотя я должен искать, если это связано с штрафом за производительность, как на большинстве языков). Правда: это облегчит мою озабоченность. Тем не менее, этот способ работы мешает мне смотреть на частичные результаты, прежде чем все это закончится. Обратите внимание, что я высоко ценю предложение Хонга, но я был в «чертовой, я начал много вещей, и мне интересно, как это делается», стул слишком часто сам :-). –  Nick Sabbe 12.05.2011 в 11:40
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
    
ответ дан mpiktas 12.05.2011 в 09:04
источник
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 не правильно выбирает имена элементов списка.

    
ответ дан James 12.05.2011 в 12:10
источник