Применение одной и той же операции над столбцами с одной и той же строкой в именах столбцов?

#r

Вопрос:

Это может быть очень простой вопрос, но я чувствую, что у меня есть два разных ответа, которые полезны, но трудно собрать воедино. Это также мой первый вопрос по StackOverflow, так что вот он:

У меня есть рамка данных, которая представляет собой измерения химического процесса. Существуют такие названия столбцов, как Воздушный клапан, клапан давления, уровень масла, уровень давления и т.д. Значения в этих столбцах являются либо NA, либо целым числом.

например:

 AirValve <-c(rep(1,3),rep(2,5),rep(3,8),rep(4,4)) PressureLevel<-c(12,NA,NA,15,NA,NA,NA,NA,14,NA,NA,NA,NA,NA,NA,NA,16,NA,NA,NA) df1<-data.frame(AirValve,PressureLevel)
 

Я должен включить все NAs в 0, но только в определенных столбцах со словом «Уровень» в названии.

Если бы это был просто уровень давления df1$, я мог бы сделать:

 df1$PressureLevel[is.na(df1$PressureLevel)] <- 0
 

Но есть много других столбцов с «Уровнем» в названии.

Я также знаю, что grepl можно использовать как таковой:

 grepl("Level", names(df1))
 

но не знаю точно, что он делает или как его можно использовать вместе с предыдущей строкой.

Как бы я превратил значения NA в 0 значений только в столбцах, которые удовлетворяют этому условию grepl?

Ответ №1:

Вы ищете contains() помощника по выбору здесь.

С помощью dplyr мы можем мутировать across() столбцы, которые contains() шаблон «выравнивает», и replace() эти значения с 0.

 library(dplyr)

df1 %>% mutate(across(contains("Level"), ~replace(.x, is.na(.x), 0)))
 

функция replace() обычно является более общей и может использоваться для замены различных значений. В частности, для NAs мы также можем использовать coalesce() или replace_na :

 library(dplyr)

df1 %>% mutate(across(contains("Level"), ~coalesce(.x, 0)))

#OR

df1 %>% mutate(across(contains("Level"), replace_na, 0))
 

выход

    AirValve PressureLevel
1         1            12
2         1             0
3         1             0
4         2            15
5         2             0
6         2             0
7         2             0
8         2             0
9         3            14
10        3             0
11        3             0
12        3             0
13        3             0
14        3             0
15        3             0
16        3             0
17        4            16
18        4             0
19        4             0
20        4             0
 

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

1. Там также есть replace_na : mutate(across(contains("Level"), replace_na, 0))

2. да, вы правы, еще раз спасибо, andrew_reece, за то, что немного улучшили ответ

3. Спасибо вам за это! Если бы вместо замены NAs на 0 я хотел сделать что-то еще в тех же столбцах (например, скопировать значения из предыдущей строки), я бы просто написал что-то еще в разделе «объединение» или «замена»?

4. С across(selection_helper) помощью вы можете выбирать столбцы с несколькими различными критериями (сопоставление имен с «содержит», «starts_with» и т. Д., логическая индексация с «где» и т. Д.). Затем вы можете выполнить любую операцию над столбцом с .fns аргументом across

5. Пример: df1 %>% mutate(across(contains('Level'), function(x) x 1)) добавим 1, чтобы выполнить все значения в выбранных столбцах

Ответ №2:

Мы можем использовать тот же вариант

 nm1 <- grepl("Level", names(df1))
df1[nm1][is.na(df1[nm1])] <- 0
 

Если мы хотим заменить элементы NA на предыдущие не-NA

 library(dplyr)
library(tidyr)
df1 %>%
     group_by(x1) %>%
     fill(x2)
 

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

1. Спасибо! Если бы вместо замены NAs на 0s я хотел сделать что-то, описанное в этой ссылке , где я заменил все значения NA первым предыдущим значением, отличным от NA. Код по ссылке : df1$x2

2. @user2499554 вы можете использовать fill в обновлении