Как заменить все значения в нескольких столбцах, которых нет в числе значений в другом столбце

#r #replace #na

Вопрос:

У меня есть набор данных с одной переменной с идентификаторами участников и несколькими переменными с одноранговыми номинациями (в виде идентификаторов).

Мне нужно заменить все числа в переменных одноранговой номинации, которые не входят в число идентификаторов участников, на NA.

Пример: У меня есть

 ID       PN1       PN2
1         2         5
2         3         4
4         6         2      
5         2         7
 

Мне нужно

 ID       PN1       PN2
1         2         5
2         NA        4
4         NA        2      
5         2         NA
 

Было бы здорово, если бы кто-нибудь мог помочь! Заранее большое вам спасибо.

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

1. Пожалуйста, используйте dput() для подготовки воспроизводимых примеров данных.

Ответ №1:

Альтернатива с Base R ,

 df[,-1][matrix(!(unlist(df[,-1]) %in% df[,1]),nrow(df))] <- NA
df
 

дает,

   ID PN1 PN2
1  1   2   5
2  2  NA   4
3  4  NA   2
4  5   2  NA
 

Ответ №2:

 library(tidyverse)

df %>%
  mutate(across(-ID, ~if_else(. %in% ID, ., NA_real_)))
 

что дает:

 #   ID PN1 PN2
# 1  1   2   5
# 2  2  NA   4
# 3  4  NA   2
# 4  5   2  NA
 

Используемые данные:

 df <- data.frame(ID = c(1, 2, 4, 5),
                 PN1 = c(2, 3, 6, 2),
                 PN2 = c(5, 4, 2, 7))
 

Ответ №3:

Вот базовый способ R.
lapply Цикл для всех столбцов, кроме столбца идентификатора, использует функцию is.na<- для присвоения NA значений элементам вектора, в которых их нет df1[[1]] . Затем возвращает измененный вектор.

 df1[-1] <- lapply(df1[-1], function(x){
  is.na(x) <- !x %in% df1[[1]]
  x
})

df1
#  ID PN1 PN2
#1  1   2   5
#2  2  NA   4
#3  4  NA   2
#4  5   2  NA
 

Данные в dput формате

 df1 <-
structure(list(ID = c(1L, 2L, 4L, 5L), 
PN1 = c(2L, NA, NA, 2L), PN2 = c(5L, 4L, 2L, NA)), 
row.names = c(NA, -4L), class = "data.frame")
 

Ответ №4:

Мы могли бы использовать mutate с case_when :

 library(dplyr)
df %>% 
  mutate(across(starts_with("PN"), ~case_when(!(. %in% ID) ~ NA_real_,
                                              TRUE ~ as.numeric(.))))
    
 

Выход:

 # A tibble: 4 x 3
     ID   PN1   PN2
  <int> <dbl> <dbl>
1     1     2     5
2     2    NA     4
3     4    NA     2
4     5     2    NA
 

Ответ №5:

С помощью data.table вы можете (l)применить функцию fifelse() к каждому столбцу, выбранному с .SD помощью amp; .SDcols .

 require(data.table)

cols = grep('PN', names(df)) # column indices (or names)
df[ , lapply(.SD, function(x) fifelse(!x %in% ID, NA_real_, x)),
    .SDcols = cols ]
 

Данные от @deschen:

 df = data.frame(ID = c(1, 2, 4, 5),
                PN1 = c(2, 3, 6, 2),
                PN2 = c(5, 4, 2, 7))
setDT(df)