如何移动嵌套小标题中的小标题列?

How can I shift columns of tibbles in a nested tibble?

我有一个包含很多类别的数据框。对于一个类别,我计算一个移动值。使用这个值,我想将数据框这部分的每一列向下移动这个值。要执行此操作,我认为使用 "nested tibble" 然后使用 purrrmap 函数来执行移位可能很有用。

为了人为地重现这个问题,我会用 iris 数据集创建这样一个数据框:

df <- iris %>% group_by(Species) %>% 
  nest() %>% mutate(shift = as.integer(c(1, 2, 3)))

df

# A tibble: 3 x 3
  Species    data              shift
  <fct>      <list>            <int>
1 setosa     <tibble [50 x 4]>     1
2 versicolor <tibble [50 x 4]>     2
3 virginica  <tibble [50 x 4]>     3

我的意图是使用一个映射函数,它获取 "data" 中的每一列 tibbles 并按移位值移动它们。在代码中(不是 运行,只是为了澄清:

df %>% mutate(data.shift = map(data, lag(.x, n = shift)))

我想要这样的输出:

# A tibble: 3 x 4
  Species    data              shift    data.shift
  <fct>      <list>            <int>    <list>
1 setosa     <tibble [50 x 4]>     1    <tibble[50 x 4]>
2 versicolor <tibble [50 x 4]>     2    <tibble[50 x 4]>
3 virginica  <tibble [50 x 4]>     3    <tibble[50 x 4]>

其中 "data.shift" 的每一列都有值偏移的滞后。例如,对于第一行,未嵌套的 tibble 看起来像:

# A tibble: 50 x 4
   Sepal.Length Sepal.Width Petal.Length Petal.Width
          <dbl>       <dbl>        <dbl>       <dbl>
 1        NA          NA           NA         NA    
 2         5.10        3.50         1.40       0.200
 3         4.90        3.00         1.40       0.200
 4         4.70        3.20         1.30       0.200
 5         4.60        3.10         1.50       0.200
 6         5.00        3.60         1.40       0.200
 7         5.40        3.90         1.70       0.400
 8         4.60        3.40         1.40       0.300
 9         5.00        3.40         1.50       0.200
10         4.40        2.90         1.40       0.200
# ... with 40 more rows

有没有办法使用 purrr::map 函数执行此操作?

这是你想要的吗?

df %>% mutate(data.shift = map2(data, shift, ~mutate_all(.x, function(z) lag(z, .y)))

我们也可以不用匿名调用,如果我们指定参数名

df %>% 
    mutate(data.shift = map2(data, shift, ~ .x %>% 
                                               mutate_all(lag, n = .y))) 

或使用 data.table shift 可以用 data.table 或 data.frame 移动

library(data.table)
df %>% 
   mutate(data.shift = map2(data, shift, ~  
          as.data.table(.x)[, (names(.x)) := shift(.SD, n = .y)]))