取消列出单个值列表的列

时间:2018-11-07 15:38:02

标签: r dplyr purrr

我一直在生成一些用于聚类的功能,并且需要基于随时间提交的客户索赔的相关系数。我使用此代码通过对嵌套的数据小块运行lm模型来获取系数:

provProfileTemp <- byProvProfile %>% 
  mutate(date = ymd(paste(Year, Month, "01", sep = "-"))) %>% 
  select(-Month, -Year) %>% 
  group_by(AccountNumber, date) %>% 
  count() %>% 
  group_by(AccountNumber) %>% 
  mutate(total_claims = sum(n)) %>% 
  ungroup() %>% 
  mutate(numeric_date = as.numeric(date)/(24*60*60)) %>% # POSIX conversion for summary(lm)
  select(AccountNumber, numeric_date, claims = n, total_claims) %>% 
  nest(-AccountNumber, -total_claims)

coeffs <- provProfileTemp %>% 
  mutate(
    fit = map(provProfileTemp$data, ~lm(numeric_date ~ claims, data = .)), 
    results = map(fit, summary, correlation = TRUE), 
    coeff = results %>% map(c("correlation")) %>% map(3)
  ) %>% 
 select(AccountNumber, coeff, total_claims) 

最上面的块创建回归线所需的变量,并将数据嵌套到带有帐号,总索赔额和回归数据的小标题的小标题中。在第二个块中使用purrr::map,我可以拟合一行,从摘要中获取结果,并从摘要中提取系数。

结果是正确的并且可以正常工作,但是,新列是其中包含系数的单个值的列表。我无法压缩列表以将新列仅用作系数而不是列表。使用unlist()会出现以下错误:Error in mutate_impl(.data, dots) : Column coeff must be length 27768 (the number of rows) or one, not 21949。发生这种情况是因为unlist()没有返回相同数量的元素。我在使用purrr::flattenunlist(lapply(coeff, "[[", 1))之类的函数时也得到了类似的结果。

关于如何将列表适当地展平为单个值或以其他方式解决问题的任何建议,这些都不需要生成这样的系数?任何帮助是极大的赞赏。谢谢。

这是数据的样子:

AccountNumber       coeff  total_claims
        <int>      <list>         <int>
           16   <dbl [1]>           494     
           19   <dbl [1]>           184     
           45   <dbl [1]>            81...

这是伪数据:

provProfileTemp <- structure(list(AccountNumber = c(1L, 1L, 1L, 1L, 
     1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 
     2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L
     ), Year = c(2018L, 2017L, 2018L, 2018L, 2018L, 2017L, 2018L, 
     2018L, 2018L, 2018L, 2018L, 2018L, 2018L, 2018L, 2018L, 2018L, 
     2018L, 2018L, 2018L, 2018L), Month = c(4L, 11L, 1L, 1L, 3L, 10L, 
     1L, 3L, 7L, 1L, 5L, 10L, 5L, 2L, 4L, 4L, 4L, 3L, 2L, 1L)), .Names =               c("AccountNumber", 
     "Year", "Month"), row.names = c(NA, -20L), class = c("tbl_df", 
     "tbl", "data.frame"))

1 个答案:

答案 0 :(得分:2)

您的评论是关于丢失一些数据和lm()不产生任何内容的评论。

首先,让我们创建一个方案,其中仅一个组的解释变量具有单个值。这样会产生map_dbl()和unnest()`等错误。

library(purrr)
library(tidyr)
library(dplyr)

mtcars$wt2 = mtcars$wt
mtcars$wt2[mtcars$cyl == 4] = NA
mtcars$wt2[3] = 1

mtcars %>% 
    group_by(cyl) %>% 
    nest() %>% 
    mutate(fit = map(data, ~ lm(mpg ~ wt2, data = .x)), 
           results = map(fit, summary, correlation = TRUE), 
           coef = results %>% map(c("correlation")) %>% map_dbl(3))
  

mutate_impl(.data,点)中的错误:评估错误:结果2为   不是长度为1的原子向量。

这是因为结果之一是NULL

mtcars %>% 
    group_by(cyl) %>% 
    nest() %>% 
    mutate(fit = map(data, ~ lm(mpg ~ wt2, data = .x)), 
           results = map(fit, summary, correlation = TRUE), 
           coef = results %>% map(c("correlation")) %>% map(3)) %>%
    pull(coef)

[[1]]
[1] -0.9944458

[[2]]
NULL

[[3]]
[1] -0.983668

因此,您需要用某种替换NULL(或在进行模型拟合之前删除没有足够数据的行,这可能是最简单的解决方案)。我经常在这种情况下使用possibly(),尽管这对于您的情况而言比较困难。我最终遵循了this answer,但是我敢肯定还有其他方法/工具可以做到这一点。

只要相关矩阵中没有第三个值,我都会返回NA_real_

mtcars %>% 
    group_by(cyl) %>% 
    nest() %>% 
    mutate(fit = map(data, ~ lm(mpg ~ wt2, data = .x)), 
           results = map(fit, summary, correlation = TRUE), 
           coef = results %>% map(c("correlation")) %>% 
               map_dbl(., possibly(~.x[3], NA_real_)))

# A tibble: 3 x 5
    cyl data               fit      results             coef
  <dbl> <list>             <list>   <list>             <dbl>
1     6 <tibble [7 x 11]>  <S3: lm> <S3: summary.lm>  -0.994
2     4 <tibble [11 x 11]> <S3: lm> <S3: summary.lm>  NA    
3     8 <tibble [14 x 11]> <S3: lm> <S3: summary.lm>  -0.984