排除列时跨变异的正确语法

Correct syntax for mutate across when excluding columns

我正在尝试将代码从使用 mutate_at 转换为使用 mutate(across())。我假设我有一个语法错误,但在尝试解决 45 分钟后我决定是时候参与这个论坛了。

可重现的例子:

library(tidyverse)

df_initial <- structure(list(Date = structure(c(18684, 18685, 18686, 18684, 
                                                18685, 18686, 18684, 18685, 18686, 18684, 18685, 18686, 18684, 
                                                18685, 18686, 18684, 18685, 18686, 18684, 18685, 18686, 18684, 
                                                18685, 18686, 18684, 18685, 18686, 18684, 18685, 18686), class = "Date"), 
                             index_name = c("INDU Index", "INDU Index", "INDU Index", 
                                            "SPX Index", "SPX Index", "SPX Index", "MID Index", "MID Index", 
                                            "MID Index", "SML Index", "SML Index", "SML Index", "CCMP Index", 
                                            "CCMP Index", "CCMP Index", "RTY Index", "RTY Index", "RTY Index", 
                                            "S5INFT Index", "S5INFT Index", "S5INFT Index", "S5FINL Index", 
                                            "S5FINL Index", "S5FINL Index", "S5HLTH Index", "S5HLTH Index", 
                                            "S5HLTH Index", "S5CONS Index", "S5CONS Index", "S5CONS Index"
                             ), index_level = c(30932.37, NA, NA, 3811.15, NA, NA, 2496.26, 
                                                NA, NA, 1278.56, NA, NA, 13192.35, NA, NA, 2201.051, NA, 
                                                NA, 2293.4, NA, NA, 535.64, NA, NA, 1311.27, NA, NA, 649.39, 
                                                NA, NA), totalReturn_daily = c(-1.4628, 0, 0, -0.4636, 0, 
                                                                               0, -0.0888, 0, 0, -0.3891, 0, 0, 0.5587, 0, 0, 0.0507, 0, 
                                                                               0, 0.5991, 0, 0, -1.9617, 0, 0, -0.8079, 0, 0, -1.6277, 0, 
                                                                               0)), row.names = c(NA, -30L), groups = structure(list(index_name = c("CCMP Index", 
                                                                                                                                                    "INDU Index", "MID Index", "RTY Index", "S5CONS Index", "S5FINL Index", 
                                                                                                                                                    "S5HLTH Index", "S5INFT Index", "SML Index", "SPX Index"), .rows = structure(list(
                                                                                                                                                      13:15, 1:3, 7:9, 16:18, 28:30, 22:24, 25:27, 19:21, 10:12, 
                                                                                                                                                      4:6), ptype = integer(0), class = c("vctrs_list_of", "vctrs_vctr", 
                                                                                                                                                                                          "list"))), row.names = c(NA, 10L), class = c("tbl_df", "tbl", 
                                                                                                                                                                                                                                       "data.frame"), .drop = TRUE), class = c("grouped_df", "tbl_df", 
                                                                                                                                                                                                                                                                               "tbl", "data.frame"))

head(df_initial)


# A tibble: 6 x 4
# Groups:   index_name [2]
  Date       index_name index_level totalReturn_daily
  <date>     <chr>            <dbl>             <dbl>
1 2021-02-26 INDU Index      30932.            -1.46 
2 2021-02-27 INDU Index         NA              0    
3 2021-02-28 INDU Index         NA              0    
4 2021-02-26 SPX Index        3811.            -0.464
5 2021-02-27 SPX Index          NA              0    
6 2021-02-28 SPX Index          NA              0 

我之前使用 mutate_at 的代码工作正常:

df1 <- df_initial %>%
  mutate_at(vars(-index_name, -totalReturn_daily),
            ~ na.locf(., na.rm = FALSE)
  )

head(df1)
# A tibble: 6 x 4
# Groups:   index_name [2]
  Date       index_name index_level totalReturn_daily
  <date>     <chr>            <dbl>             <dbl>
1 2021-02-26 INDU Index      30932.            -1.46 
2 2021-02-27 INDU Index      30932.             0    
3 2021-02-28 INDU Index      30932.             0    
4 2021-02-26 SPX Index        3811.            -0.464
5 2021-02-27 SPX Index        3811.             0    
6 2021-02-28 SPX Index        3811.             0  

当我尝试使用它转换为 mutateacross 时,出现错误:

df2 <- df_initial %>%
  mutate(across(.cols = -c(index_name, totalReturn_daily),
                .fns  = ~ na.locf(., na.rm = FALSE)
  )
  )

Error: Can't subset elements that don't exist.
x Location 56 doesn't exist.
i There are only 10 elements.
Run `rlang::last_error()` to see where the error occurred.

我怀疑错误源于试图排除 .cols = 行中的列,但我尝试了 .cols = !c(index_name, totalReturn_daily).cols = c(-index_name, -totalReturn_daily) 甚至 .cols != c(index_name, totalReturn_daily) 但我得到了同样的错误。

感谢您的帮助!

您的数据按 index_name 分组,across 找不到分组的列。先尝试 ungroup 数据 :

library(dplyr)
df_initial %>%
  ungroup %>%
  mutate(across(.cols = -c(index_name, totalReturn_daily),
                .fns  = ~ na.locf(., na.rm = FALSE)))