以不同方式对每个组进行预测

问题描述 投票:2回答:3

我的数据集看起来像这样:

Category Weekly_Date             a             b
   <chr>    <date>           <dbl>         <dbl>
 1   aa     2018-07-01        36.6          1.4
 2   aa     2018-07-02        5.30          0   
 3   bb     2018-07-01        4.62          1.2
 4   bb     2018-07-02        3.71          1.5
 5   cc     2018-07-01        3.41          12
... ...            ...         ...          ...

我分别为每个组拟合线性回归:

fit_linreg <- train %>%
              group_by(Category) %>%
              do(model = lm(Target ~ Unit_price + Unit_discount, data = .)) 

现在我对每个类别都有不同的模型:

aa model1
bb model2
cc model3

所以,我需要将每个模型应用到适当的类别。怎么实现呢? (dplyr更好)

r dplyr time-series grouping forecasting
3个回答
5
投票

如果嵌套测试数据的数据,将其与模型连接,则可以使用map2使用经过训练的模型对测试数据进行预测。请参阅下面的mtcars示例。

library(tidyverse)

x <- mtcars %>% 
  group_by(gear) %>% 
  do(model = lm(mpg ~ hp + wt, data = .)) 

x
Source: local data frame [3 x 2]
Groups: <by row>

# A tibble: 3 x 2
   gear model   
* <dbl> <list>  
1     3 <S3: lm>
2     4 <S3: lm>
3     5 <S3: lm>

mtcars %>% 
  group_by(gear) %>% 
  nest %>% 
  inner_join(x) %>% 
  mutate(preds = map2(model, data, predict)) %>% 
  unnest(preds)

  Joining, by = "gear"
# A tibble: 32 x 2
    gear preds
   <dbl> <dbl>
 1     4  22.0
 2     4  21.2
 3     4  25.1
 4     4  26.0
 5     4  22.2
 6     4  17.8
 7     4  17.8
 8     4  28.7
 9     4  32.3
10     4  30.0
# ... with 22 more rows

1
投票

这是一种方法,我使用data.table进行过滤,但你也可以使用dplyr,我只是更喜欢data.table语法。

d <- as.data.table(mtcars)
cats <- unique(d$cyl)

m <- lapply(cats, function(z){
  return(lm(formula = mpg ~ wt + hp + disp, 
            data = d[cyl == z, ] ))
})

names(m) <- cats

OUTPUT

> summary(m)
  Length Class Mode
6 12     lm    list
4 12     lm    list
8 12     lm    list

# Checking first model 
> m[[1]]

Call:
lm(formula = mpg ~ wt + hp + disp, data = d[cyl == z, ])

Coefficients:
(Intercept)           wt           hp         disp  
   30.27791     -3.89618     -0.01097      0.01610 

> sapply(1:length(m), function(z) return(summary(m[[z]])$adj.r.squared))
[1] 0.4434228 0.5829574 0.3461900

我将列表命名为因为在您的情况下,可能更容易通过名称aabb来引用模型。希望这可以帮助!


1
投票

我发现嵌套和非嵌套非常不自然,所以这是我的尝试。

假设您希望模型的质量合适。

library(dplyr)

mtcars %>%
  group_by(cyl) %>%
  do(data.frame(r2 = summary(lm(mpg ~ wt, data = .))$r.squared))
#> # A tibble: 3 x 2
#> # Groups:   cyl [3]
#>     cyl    r2
#>   <dbl> <dbl>
#> 1     4 0.509
#> 2     6 0.465
#> 3     8 0.423

假设您想要残差:

library(dplyr)
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union

mtcars %>%
  group_by(cyl) %>%
  do(data.frame(resid = residuals(lm(mpg ~ wt, data = .))))
#> # A tibble: 32 x 2
#> # Groups:   cyl [3]
#>      cyl   resid
#>    <dbl>   <dbl>
#>  1     4 -3.67  
#>  2     4  2.84  
#>  3     4  1.02  
#>  4     4  5.25  
#>  5     4 -0.0513
#>  6     4  4.69  
#>  7     4 -4.15  
#>  8     4 -1.34  
#>  9     4 -1.49  
#> 10     4 -0.627 
#> # ... with 22 more rows

请参阅?do,了解为什么需要嵌入式data.frame()。您可能希望在结果中包含其他列。不仅仅是分组变量和残差。除了列出它们之外,我找不到一个简洁的方法来做到这一点!

library(dplyr)

mtcars %>%
  group_by(cyl) %>%
  do(data.frame(disp = .$disp, 
                qsec = .$qsec,
                resid = residuals(lm(mpg ~ wt, data = .))))
#> # A tibble: 32 x 4
#> # Groups:   cyl [3]
#>      cyl  disp  qsec   resid
#>    <dbl> <dbl> <dbl>   <dbl>
#>  1     4 108    18.6 -3.67  
#>  2     4 147.   20    2.84  
#>  3     4 141.   22.9  1.02  
#>  4     4  78.7  19.5  5.25  
#>  5     4  75.7  18.5 -0.0513
#>  6     4  71.1  19.9  4.69  
#>  7     4 120.   20.0 -4.15  
#>  8     4  79    18.9 -1.34  
#>  9     4 120.   16.7 -1.49  
#> 10     4  95.1  16.9 -0.627 
#> # ... with 22 more rows

一些不起作用的东西

对于第一个例子,我认为以下内容可行:

library(dplyr)

mtcars %>%
  group_by(cyl) %>%
  summarise(r2 = summary(lm(mpg ~ wt, data = .))$r.squared)
#> # A tibble: 3 x 2
#>     cyl    r2
#>   <dbl> <dbl>
#> 1     4 0.753
#> 2     6 0.753
#> 3     8 0.753

但是你可以看到所有型号都有相同的r2。这是因为模型适合所有数据,而不是cyl。看一下作者的代码,我相信这是因为他们使用Rcpp优化了对mutate()summarise()的评估,并且优化在这种情况下不起作用。但do()按预期工作。它在将数据传递给要评估的表达式之前按组对数据进行子集。我看到他们正在思考这个问题,请参阅Hyrbid Folding

© www.soinside.com 2019 - 2024. All rights reserved.