Динамически выбирать все столбцы, но среди тех, которые начинаются с определенного слова, исключить все, кроме одного - PullRequest
0 голосов
/ 12 октября 2018

У меня есть много фреймов данных, которые имеют такой формат:

df1 <- structure(list(ID = 1:2, Name = 1:2, Gender = 1:2, Group = 1:2, 
                      FORMULA_RULE = 1:2, FORMULA_TRANSFORM = 1:2, FORMULA_UNITE = 1:2, 
                      FORMULA_CALCULATE = 1:2, FORMULA_JOIN = 1:2), class = "data.frame", row.names = c(NA, 
                                                                                                        -2L))

df2 <- structure(list(ID = 1:2, Name = 1:2, Gender = 1:2, FORMULA_RULE = 1:2, 
    FORMULA_META = c(NA, NA), FORMULA_DATA = 1:2, FORMULA_JOIN = 1:2, 
    FORMULA_TRANSFORM = 1:2, Group = 1:2), class = "data.frame", row.names = c(NA, 
-2L))

Представление:

df1
  ID Name Gender Group FORMULA_RULE FORMULA_TRANSFORM FORMULA_UNITE FORMULA_CALCULATE FORMULA_JOIN
1  1    1      1     1            1                 1             1                 1            1
2  2    2      2     2            2                 2             2                 2            2

df2
  ID Name Gender FORMULA_RULE FORMULA_META FORMULA_DATA FORMULA_JOIN FORMULA_TRANSFORM Group
1  1    1      1            1           NA            1            1                 1     1
2  2    2      2            2           NA            2            2                 2     2

Я хочу написать код, который будет работать на всех таких фреймах данных втаким образом, что все столбцы сохраняются, но среди столбцов, начинающихся с FORMULA_, выбирается только FORMULA_TRANSFORM.Обратите внимание, что столбцы, которые НЕ начинаются с FORMULA_, не всегда одинаковы, то есть я не могу просто написать код, который всегда выбирает ID, Name, Gender, Group и FORMULA_TRANSFORM, потому что есть некоторые фреймы данных, которые содержат много других столбцов, которые не начинаются с FORMULA_, которые я хочу сохранить.

My попытка решить эту проблему - это уродливый код, который работает , как и ожидалось:

library(tidyverse)
for(i in 1:length(ls(pattern = "df"))){

    get(paste0("df", i)) %>% 
        select(-starts_with("FORMULA"), 
               (names(get(paste0("df", i))) %>% grep(pattern = "FORMULA", value = T))[!names(get(paste0("df", i))) %>% grep(pattern = "FORMULA", value = T)  %in% "FORMULA_TRANSFORM"]) 
    %>% print

}

Есть ли более прямой способ сделать это?

1 Ответ

0 голосов
/ 12 октября 2018

С dplyr мы можем использовать select, и это довольно просто, используя starts_with и contains.

library(dplyr)
df1 %>%
   select(-starts_with("FORMULA_"), contains("FORMULA_TRANSFORM"))


#  ID Name Gender Group FORMULA_TRANSFORM
#1  1    1      1     1                 1
#2  2    2      2     2                 2

Давайте попробуем с фреймом данных без столбца "FORMULA_TRANSFORM"

df3 <- df1
df3$FORMULA_TRANSFORM <- NULL

df3 %>%
   select(-starts_with("FORMULA_"), contains("FORMULA_TRANSFORM"))

#  ID Name Gender Group
#1  1    1      1     1
#2  2    2      2     2

со знаком минус мы удаляем столбцы, которые starts_with "FORMULA_", и выбираем столбец с "FORMULA_TRANSFORM".Вместо contains мы также можем использовать one_of() или matches(), и он все равно будет работать.


Используя базу R, мы можем использовать grep с invert и value, установленными какTRUE

df1[c(grep("^FORMULA_", names(df1), invert = TRUE, value = TRUE),
                                           "FORMULA_TRANSFORM")]

#  ID Name Gender Group FORMULA_TRANSFORM
#1  1    1      1     1                 1
#2  2    2      2     2                 2

Это создает вектор имен столбцов, где имя столбца не начинается с «FORMULA_», и мы позже добавляем «FORMULA_TRANSFORM» вручную.

В приведенном выше методе предполагается, чтоу вас всегда есть столбец "FORMULA_TRANSFORM" в вашем фрейме данных, и если он не будет, произойдет сбой.Более безопасный вариант будет

get_selected_cols <- function(df1) {
    cbind(df1[grep("^FORMULA_", names(df1), invert = TRUE)], 
        df1[names(df1) == "FORMULA_TRANSFORM"])
 }
get_selected_cols(df1)

#  ID Name Gender Group FORMULA_TRANSFORM
#1  1    1      1     1                 1
#2  2    2      2     2                 2


get_selected_cols(df3)

#  ID Name Gender Group
#1  1    1      1     1
#2  2    2      2     2
...