摆脱嵌套(不必要的)for循环

时间:2019-01-17 14:39:01

标签: r for-loop

我在Fortran中经验丰富,但是在R中是一个新手。在Fortran中,我习惯嵌套几个do-loop,但是我想R中有更好的方法。通过应用apply可以回答其他一些问题,但我不确定这对我来说是否正确。

我想对模型数据进行偏差校正。我知道有针对此的软件包,但是我更愿意自己编写代码。我有两个data.frame,第一个包含我的模型数据:

library(dplyr)
x <- round(runif(34698,0,20), 2)
df_a <- data.frame(date=as.Date(0:34697, origin="2006-01-01"),x)
df_a <- setNames(df_a, c("date","daily"))
df_a <- separate(df_a, date, into = c("year", "month", "day"), sep="-")

第二个数据框包含观察和建模的历史月度平均值:

df_b <- data.frame(month=seq(01,12,by=1),obs=seq(1.1,12.1,by=1),model=seq(2.2,13.2,by=1))
df_b$month <- ifelse(nchar(df_b$month)!=2,paste0("0",df_b$month),df_b$month)

通过以下代码,我将使用第二个data.frame每个月的方式来更正我的第一个data.frame的数据。该代码可以正常工作,但是我认为它不是R风格的代码。特别是,我将需要更多的for循环,因为我有多个模型输出,并且对于每个模型,我有两种不同的情况。

system.time(
  for(i in 1:12){
    for (j in 1:nrow(df_a)) {
      if(df_b$month[i]==df_a$month[j]){
        df_a$daily[j] <- df_a$daily[j]+(df_b$obs[i]-df_b$model[i])
      }
    }
  }
)

我真的很感激任何人都可以向我展示如何“改进” R语言中的编码风格。

1 个答案:

答案 0 :(得分:4)

更好的选择是进行left_joinmutate创建新列

library(dplyr)
df_a1 <- df_a %>% 
            left_join(df_b) %>% 
            mutate(daily = daily + obs + model)

基准

system.time(df_a %>% 
              left_join(df_b) %>%
              mutate(daily = daily + obs + model))  
#   user  system elapsed 
#  0.201   0.011   0.213 

此外,正如评论中提到的@parfait一样,带有base R的{​​{1}}版本将是

merge

或与system.time( within(merge(df_a, df_b, by="month", all.x=TRUE), { daily <- daily + obs + model})) # user system elapsed # 0.260 0.015 0.275

data.table

和OP的library(data.table) system.time(setDT(df_a)[df_b, daily := daily + obs + model, on = .(month)]) # user system elapsed # 0.198 0.011 0.208 循环

for