我有一个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。
答案 0 :(得分:0)
这适合“多种模型”模式,在这种模式下,我们希望将数据分为几组,将模型应用于每个组,然后提取该模型的结果以进行汇总。
在tidyverse
+ tidymodels
的世界中,这是通过组合以下内容来实现的:
tidyr::nest()
,为每个组创建数据框列purrr::map()
,这使我们可以将函数应用于列表/列的每个元素。broom::tidy()
,它构建了模型输出的更有用的数据框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
有关此模式的更多信息,尤其是在这里使用broom
和tidymodels
方法:summary dataframe from several multiple regression outputs。 (而且,评论者已经添加了非tidymodels
方法。)