Существует ли решение tidyverse для изменения значений нескольких столбцов на определенное значение. R

#r #dplyr #tidyverse #contains

Вопрос:

Итоги вакцинации в США от CDC с использованием tidyverse/dplyr

Исходный набор данных извлекается из https://covid.cdc.gov/covid-data-tracker/#vaccinations_vacc-total-admin-rate-total

Я перехожу к краткому изложению переменных, представляющих интерес. Мое желание здесь состоит в том, чтобы изменить столбцы, содержащие «PCT», на NA, так как сумма процентов не имеет смысла.

 # summarise_all(CDC_vacc_State, ~if(is.numeric(.)) sum(., na.rm = T) else "National")
 

Здесь я собираюсь вывести набор данных. Здесь мы видим, что существует 8 столбцов, содержащих «PCT».
Я понимаю, что население моей страны сократилось на 1,2 млн человек, я решил это на основе данных, а не путем объединения данных переписи.

 # dput(summarise_all(CDC_vacc_State, ~if(is.numeric(.)) sum(., na.rm = T) else "National"))

df <- structure(
  list(
    STATE = "National",
    ONE_DOSE_NUM = 220978782,
    ONE_DOSE_PCT = 3752.9,
    FULL_DOSE_NUM = 190719566,
    FULL_DOSE_PCT = 3276.7,
    POP = 334203604,
    ONE_DOSE_NUM_18Plus = 206114881,
    ONE_DOSE_PCT_18Plus = 4412.7,
    FULL_DOSE_NUM_18Plus = 178587829,
    FULL_DOSE_PCT_18Plus = 3883.9,
    POP_18Plus = 258316189,
    ONE_DOSE_NUM_65Plus = 53312849,
    ONE_DOSE_PCT_65Plus = 5112.9,
    FULL_DOSE_NUM_65Plus = 47324330,
    FULL_DOSE_PCT_65Plus = 4652.6,
    POP_65Plus = 55128330,
    ONE_DOSE_NUM_12Plus = 219898471,
    ONE_DOSE_PCT_12Plus = 4258.4,
    FULL_DOSE_NUM_12Plus = 189835922,
    FULL_DOSE_PCT_12Plus = 3733.8,
    POP_12Plus = 282154872
  ),
  class = c("tbl_df", "tbl", "data.frame"),
  row.names = c(NA,-1L)
)
 

Измените значения в столбцах, содержащих «PCT», на NA с помощью tidyverse?

Я нашел решение, но я надеялся сделать это встроенным с помощью dplyr и использовать bind_rows() или rbindlist() с исходным набором данных.

 # this is my current solution
df[,names(select(df, contains('PCT')))] <- NA  

 

Окончательный набор данных выглядит следующим образом

 dput(df)

structure(list(STATE = "National", ONE_DOSE_NUM = 220978782, 
    ONE_DOSE_PCT = NA, FULL_DOSE_NUM = 190719566, FULL_DOSE_PCT = NA, 
    POP = 334203604, ONE_DOSE_NUM_18Plus = 206114881, ONE_DOSE_PCT_18Plus = NA, 
    FULL_DOSE_NUM_18Plus = 178587829, FULL_DOSE_PCT_18Plus = NA, 
    POP_18Plus = 258316189, ONE_DOSE_NUM_65Plus = 53312849, ONE_DOSE_PCT_65Plus = NA, 
    FULL_DOSE_NUM_65Plus = 47324330, FULL_DOSE_PCT_65Plus = NA, 
    POP_65Plus = 55128330, ONE_DOSE_NUM_12Plus = 219898471, ONE_DOSE_PCT_12Plus = NA, 
    FULL_DOSE_NUM_12Plus = 189835922, FULL_DOSE_PCT_12Plus = NA, 
    POP_12Plus = 282154872), row.names = c(NA, -1L), class = c("tbl_df", 
"tbl", "data.frame"))

 

Ответ №1:

dplyr эквивалент вашего df[,names(select(df, contains('PCT')))] <- NA :

 df %>%
  mutate(across(contains("PCT"), ~NA))
 

В качестве альтернативы вы могли бы справиться с этим «нисходящим потоком», суммируя только столбцы, не относящиеся к PCT. Если вы bind_rows обратитесь к своим исходным данным, я полагаю, что столбцы PCT будут отсутствовать, поскольку их здесь не будет в результате:

 df %>%  
  summarize(across(where(is.numeric) amp; !contains("PCT"),
                   ~sum(.x, na.rm = T)))
 

Комментарии:

1. Очень полезно, спасибо за незначительные изменения, и все работает блестяще. bind_rows(CDC_vacc_State, summarise_all(CDC_vacc_State, ~if(is.numeric(.)) sum(., na.rm = T) else "National") %>% mutate(across(contains("PCT"), ~NA)) )

2. Лучший способ сделать это!