对每个组进行不同的预测

时间:2018-09-04 14:15:04

标签: r dplyr time-series grouping forecasting

我的数据集如下:

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)

3 个答案:

答案 0 :(得分: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 :(得分: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

输出

> 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来引用模型可能更容易。希望这会有所帮助!

答案 2 :(得分: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