多列分组的线性模型的R代码

时间:2019-11-19 23:08:57

标签: r linear-regression

我有一个data.frame,其中包含12个变量的5760个观察值。在我的示例中,我提供的子集仅包含32个obs和8个变量。

> (df1)
   GHGEventID    SmpDate Plot Ch SmpTime TrtIDs    ugN2O      PK
1           1 2019-06-04  101  1       0      8 7.644037 1 101 1
2           1 2019-06-04  101  1      10      8 7.420080 1 101 1
3           1 2019-06-04  101  1      20      8 7.618144 1 101 1
4           1 2019-06-04  101  1      30      8 7.612934 1 101 1
5           1 2019-06-04  101  2       0      8 7.754488 1 101 2
6           1 2019-06-04  101  2      10      8 7.979284 1 101 2
7           1 2019-06-04  101  2      20      8 7.919863 1 101 2
8           1 2019-06-04  101  2      30      8 7.719606 1 101 2
9           1 2019-06-04  202  1       0      5       NA 1 202 1
10          1 2019-06-04  202  1      10      5       NA 1 202 1
11          1 2019-06-04  202  1      20      5       NA 1 202 1
12          1 2019-06-04  202  1      30      5       NA 1 202 1
13          1 2019-06-04  202  2       0      5       NA 1 202 2
14          1 2019-06-04  202  2      10      5       NA 1 202 2
15          1 2019-06-04  202  2      20      5       NA 1 202 2
16          1 2019-06-04  202  2      30      5       NA 1 202 2
17          3 2019-06-19  101  1       0      8 8.704949 3 101 1
18          3 2019-06-19  101  1      10      8 8.897050 3 101 1
19          3 2019-06-19  101  1      20      8 8.977514 3 101 1
20          3 2019-06-19  101  1      30      8 9.307248 3 101 1
21          3 2019-06-19  101  2       0      8 9.067406 3 101 2
22          3 2019-06-19  101  2      10      8 9.194972 3 101 2
23          3 2019-06-19  101  2      20      8 8.988367 3 101 2
24          3 2019-06-19  101  2      30      8 9.378238 3 101 2
25          3 2019-06-19  202  1       0      5 8.792658 3 202 1
26          3 2019-06-19  202  1      10      5 8.988340 3 202 1
27          3 2019-06-19  202  1      20      5 9.124808 3 202 1
28          3 2019-06-19  202  1      30      5 8.977348 3 202 1
29          3 2019-06-19  202  2       0      5 8.711944 3 202 2
30          3 2019-06-19  202  2      10      5 8.981701 3 202 2
31          3 2019-06-19  202  2      20      5 9.358124 3 202 2
32          3 2019-06-19  202  2      30      5 9.381370 3 202 2
> str(df1)
'data.frame':   32 obs. of  8 variables:
 $ GHGEventID: num  1 1 1 1 1 1 1 1 1 1 ...
 $ SmpDate   : Factor w/ 30 levels "2019-06-04","2019-06-11",..: 1 1 1 1 1 1 1 1 1 1 ...
 $ Plot      : Factor w/ 24 levels "101","102","103",..: 1 1 1 1 1 1 1 1 10 10 ...
 $ Ch        : Factor w/ 2 levels "1","2": 1 1 1 1 2 2 2 2 1 1 ...
 $ SmpTime   : num  0 10 20 30 0 10 20 30 0 10 ...
 $ TrtIDs    : num  8 8 8 8 8 8 8 8 5 5 ...
 $ ugN2O     : num  7.64 7.42 7.62 7.61 7.75 ...
 $ PK        : chr  "1 101 1" "1 101 1" "1 101 1" "1 101 1" ...

我正在寻找一种基于SmpDate,Plot,Ch将线性模型应用于数据的方法,以便可以将系数用于二次计算。一个例子是

y<-c(7.644037,7.420080,7.618144,7.612934)
x<-c(0,10,20,30)
LinMod<-lm(y~x,na.action=na.exclude)$coefficients[2]*60*24*10000/(0.144032*1000000)

请注意,这不是代码的工作示例,只是为了表明我希望将这种模型应用于基于SmpDate,Plot,Ch列的每组记录。 我通过将每个SmpTime的ugN2O值拆分并作为单独的变量(列)将它们绑定回到数据帧,然后使用嵌套的for循环和索引将SmpTime值和ugN2O值分配给y和x来执行计算。如果可能的话,我希望有一个更直接的方法。 对于SmpDate=="2019-06-04"Plot=="101"Ch=="1",LinMod的结果应为0.104731726。

1 个答案:

答案 0 :(得分:0)

这适合“多种模型”模式,在这种模式下,我们希望将数据分为几组,将模型应用于每个组,然后提取该模型的结果以进行汇总。

tidyverse + tidymodels的世界中,这是通过组合以下内容来实现的:

  1. tidyr::nest(),为每个组创建数据框列
  2. purrr::map(),这使我们可以将函数应用于列表/列的每个元素。
  3. broom::tidy(),它构建了模型输出的更有用的数据框
  4. tidyr::unnest(),它需要一个数据框并转换为简单的列。

对于您的数据,我们还有几个额外的步骤,专门用于处理所有值均为NA的区域,线性模型通常会抛出错误。

代码如下:

# Wrap lm, since it throws errors
lmw <- function(data, formula) {
  tryCatch(lm(data = data, formula = formula), error = function(cond) NULL)
}  

library(tidyverse)
library(broom)
df %>% 
  nest(data = c(GHGEventID, SmpTime, TrtIDs, ugN2O, PK)) %>%
  mutate(lm_model = purrr::map(data, 
                               ~ broom::tidy(lmw(data = .x, ugN2O ~ SmpTime)))) %>%
  unnest(lm_model, keep_empty = TRUE) %>%
  filter(term != "(Intercept)" | is.na(estimate)) %>%
  mutate(LinMod = 60*24*10000/(0.144032*1000000)* estimate)

输出如下:

# A tibble: 8 x 10
  SmpDate     Plot    Ch           data term    estimate std.error statistic p.value LinMod
  <fct>      <int> <int> <list<df[,5]>> <chr>      <dbl>     <dbl>     <dbl>   <dbl>  <dbl>
1 2019-06-04   101     1        [4 × 5] SmpTime  0.00105   0.00561     0.187  0.869   0.105
2 2019-06-04   101     2        [4 × 5] SmpTime -0.00164   0.00680    -0.241  0.832  -0.164
3 2019-06-04   202     1        [4 × 5] NA      NA        NA          NA     NA      NA    
4 2019-06-04   202     2        [4 × 5] NA      NA        NA          NA     NA      NA    
5 2019-06-19   101     1        [4 × 5] SmpTime  0.0189    0.00335     5.63   0.0302  1.89 
6 2019-06-19   101     2        [4 × 5] SmpTime  0.00726   0.00778     0.933  0.449   0.726
7 2019-06-19   202     1        [4 × 5] SmpTime  0.00691   0.00565     1.22   0.346   0.690
8 2019-06-19   202     2        [4 × 5] SmpTime  0.0238    0.00508     4.70   0.0424  2.38 

有关此模式的更多信息,尤其是在这里使用broomtidymodels方法:summary dataframe from several multiple regression outputs。 (而且,评论者已经添加了非tidymodels方法。)