将后续变量的最小值累计到一列

时间:2018-10-31 14:02:26

标签: r dplyr purrr tidyeval

对于附加的数据,我想提取最少的选定列并将其累积在(Intercept)列中。其余变量应为原始变量值与减去的最小值之间的差。我编写了一个对一个选定的列执行此操作的函数,并尝试使用purrr:map_at在几个选定的列上调用它。但是下面的代码行不通-不仅没有拉出最小值,而且还返回了后续日期的列表,而我显然想保留data.frame结构。

structure(list(`2016-01-01` = c(19.612765930918, 0.0139082609319898, 
0.298043103003794, -0.217012113254805), `2016-01-02` = c(19.612765930918, 
0.153780074988214, 0.317999312583603, -0.192164881529573), `2016-01-03` = c(19.612765930918, 
0.150571795109967, 0.515644453462975, -0.269251568581305), `2016-01-04` = c(19.612765930918, 
0.142512722884255, 0.261814150174792, -0.160625206980914), `2016-01-05` = c(19.612765930918, 
0.0778498178207942, 0.464855455837326, -0.15224027496774), `2016-01-06` = c(19.612765930918, 
0.0314062544574153, 0.278014325308919, -0.19657100740319)), class = "data.frame", row.names = c("(Intercept)", 
"x1", "x2", "x3"))

min_to_base <- function(impacts, var) {
  var <- ensym(var)

  impacts %>% 
    t() %>% 
    as.data.frame() %>% 
    mutate(min = min(!!var),
           !!var := !!var - min,
           `(Intercept)` = `(Intercept)` + min) %>% 
    select(-min)
}

impacts %>% 
  map_at(c('x1', 'x2'), ~min_to_base(., .x))

1 个答案:

答案 0 :(得分:1)

因此,您要从这些列中减去x1x2的最小值,并将这些最小值添加到(Intercept)中吗?如果是这样,这应该可行

library(tidyverse)

min_to_base <- function(df, cols){
  mins <- lapply(df[cols], min)
  df[cols] <- df[cols] - mins
  df['(Intercept)'] <- df['(Intercept)'] + do.call(sum, mins)
  df
}

impacts %>% 
  t %>% 
  as_tibble(rownames = 'dt') %>% 
  min_to_base(c('x1', 'x2'))


#   dt         `(Intercept)`     x1     x2     x3
#   <chr>              <dbl>  <dbl>  <dbl>  <dbl>
# 1 2016-01-01          19.9 0      0.0362 -0.217
# 2 2016-01-02          19.9 0.140  0.0562 -0.192
# 3 2016-01-03          19.9 0.137  0.254  -0.269
# 4 2016-01-04          19.9 0.129  0      -0.161
# 5 2016-01-05          19.9 0.0639 0.203  -0.152
# 6 2016-01-06          19.9 0.0175 0.0162 -0.197

这是一种使函数表现为NSE的小技巧(与上述结果相同)。

min_to_base <- function(df, ...){
  cols <- as.character(ensyms(...))
  mins <- lapply(df[cols], min)
  df[cols] <- df[cols] - mins
  df['(Intercept)'] <- df['(Intercept)'] + do.call(sum, mins)
  df
}

impacts %>% 
  t %>% 
  as_tibble(rownames = 'dt') %>% 
  min_to_base(x1, x2)

使用的数据:

impacts <- 
structure(list(`2016-01-01` = c(19.612765930918, 0.0139082609319898, 
0.298043103003794, -0.217012113254805), `2016-01-02` = c(19.612765930918, 
0.153780074988214, 0.317999312583603, -0.192164881529573), `2016-01-03` = c(19.612765930918, 
0.150571795109967, 0.515644453462975, -0.269251568581305), `2016-01-04` = c(19.612765930918, 
0.142512722884255, 0.261814150174792, -0.160625206980914), `2016-01-05` = c(19.612765930918, 
0.0778498178207942, 0.464855455837326, -0.15224027496774), `2016-01-06` = c(19.612765930918, 
0.0314062544574153, 0.278014325308919, -0.19657100740319)), class = "data.frame", row.names = c("(Intercept)", 
"x1", "x2", "x3"))