【问题标题】:R: using customised function in dplyrR:在 dplyr 中使用自定义函数
【发布时间】:2018-02-20 16:40:58
【问题描述】:

样本数据:

      library(tidyverse)
      set.seed(123)

      dat <- tibble(
        year = rep(1980:2015, each = 100),
        day = rep(200:299, times = 36),
        rain = sample(0:17, size = 100*36,replace = T),
        PETc =  sample(rnorm(100*36)),
        ini.t = rep(10:45, each = 100 ))

我有一个在 DataFrame 上运行的函数

   my.func <- function(df, initial, thres, upper.limit){

        df$paw <- rep(NA, nrow(df))
        df$aetc <- rep(NA, nrow(df))
        df$sw <- rep(NA, nrow(df))

        for(n in 1:nrow(df)){
          df$paw[n] <- df$rain[n] + initial
          df$aetc[n] <- ifelse(df$paw[n] >= thres, df$PETc[n], (df$paw[n]/thres) * df$PETc[n])
          df$aetc[n] <- ifelse(df$aetc[n] > df$paw[n], df$paw[n], df$aetc[n])
          df$sw[n] <- initial + df$rain[n] - df$aetc[n]
          df$sw[n] <- ifelse(df$sw[n] > upper.limit,upper.limit,ifelse(df$sw[n] < 0, 0,df$sw[n]))
          initial <- df$sw[n]
}
  return(df)
}

thres &lt;- 110 upper.limit &lt;- 200

将上述函数应用于一年:

        dat.1980 <- dat[dat$year == 1980,]

        my.func(dat.1980, initial = dat.1980$ini.t[1], thres, upper.limit)

我如何将此功能应用到每一年。我想到了使用 dplyr

              dat %>% group_by(year)%>% run my function on each year. 

此外,由于有 35 年,因此将返回 35 个数据帧。如何逐行返回绑定这些数据框?

【问题讨论】:

    标签: r dataframe dplyr tidyverse


    【解决方案1】:

    你在正确的轨道上。 do 可让您按组执行功能。

    dat %>% 
       group_by(year) %>% 
       do(my.func(., initial = head(.$ini.t, 1), thres, upper.limit))
    
    # Groups: year [36]
        # year   day  rain    PETc ini.t   paw    aetc    sw
       # <int> <int> <int>   <dbl> <int> <dbl>   <dbl> <dbl>
     # 1  1980   200     5  0.968     10  15.0  0.132   14.9
     # 2  1980   201    14  0.413     10  28.9  0.108   28.8
     # 3  1980   202     7 -0.912     10  35.8 -0.296   36.1
     # 4  1980   203    15 -0.337     10  51.1 -0.156   51.2
     # 5  1980   204    16  0.412     10  67.2  0.252   67.0
     # 6  1980   205     0 -0.923     10  67.0 -0.562   67.5
     # 7  1980   206     9  1.17      10  76.5  0.813   75.7
     # 8  1980   207    16  0.0542    10  91.7  0.0452  91.7
     # 9  1980   208     9 -0.293     10 101   -0.268  101  
    # 10  1980   209     8  0.0788    10 109    0.0781 109  
    # ... with 3,590 more rows
    

    purrr::map 函数是 du jour 方法,但我认为在这种情况下这是一种风格选择

    【讨论】:

    • 非常感谢您的回复。
    • 快速问题,如果我必须按年拆分,并且每年按月拆分,以便我的函数在每个月运行。在 dplyr 我可以做dat %&gt;% group_by(year, month) %&gt;%。如何修改您的答案以再次拆分?
    • 您唯一需要更改的是group_bygroup_by(year, month) 应该可以满足您的要求。
    【解决方案2】:

    我们可以split by 'year' 然后使用mapmy.func 应用于list 中的每个拆分数据集

    library(purrr)
    dat %>% 
        split(.$year) %>% 
        map_df(~my.func(.x, initial = .x$ini.t[1], thres, upper.limit))
    

    【讨论】:

    • 一如既往地为您提供优雅的解决方案。 purrr 看起来非常不错。我会阅读更多关于它的内容。
    • @KS89 感谢 cmets。根据您提供的数据,map_dfdo 相比,plus rapide 似乎略有不同
    • 快速问题,如果我必须按年拆分,并且每年按月拆分,以便我的函数在每个月运行。在 dplyr 我可以做dat %&gt;% group_by(year, month) %&gt;%。如何修改您的答案以再次拆分?
    • @KS89 你可以做split(list(.$year, .$month), drop = TRUE)
    猜你喜欢
    • 1970-01-01
    • 2019-08-08
    • 1970-01-01
    • 2019-12-06
    • 1970-01-01
    • 1970-01-01
    • 2021-06-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多