Присвоите числовой переменной значение NA с помощью оператора IF в R

#r #if-statement #na

#r #if-оператор #na

Вопрос:

У меня есть функция, которая вычисляет разницу между строками (на основе одних и тех же столбцов) в 2 наборах данных. Вот пример и функция

 #################
##   Sample    ##
#################

# data frame for recipients

IDr= c(seq(1,4))
Blood_type_r=c("A","B","AB","O")
data_R=data.frame(IDr,Blood_type_r,A=rep(0,4),B=c(rep(0,3),1),C=c(rep(1,3),0),D=rep(1,4),E=c(rep(0,2),rep(1,1),0),stringsAsFactors=FALSE)

  data_R
  IDr Blood_type_r A B C D E
1   1            A 0 0 1 1 0
2   2            B 0 0 1 1 0
3   3           AB 0 0 1 1 1
4   4            O 0 1 0 1 0

# data frame for donors 

IDd= c(seq(1,8))
Blood_type_d= c(rep("A", each=2),rep("B", each=2),rep("AB", each=2),rep("O", each=2))
WD= c(rep(0.25, each=2),rep(0.125, each=2),rep(0.125, each=2),rep(0.5, each=2))
data_D=data.frame(IDd,Blood_type_d,A=c(rep(0,6),1,1),B=c(rep(0,6),1,1),C=c(rep(1,7),0),D=rep(1,8),E=c(rep(0,6),rep(1,1),0),WD,stringsAsFactors=FALSE)
  data_D
  IDd Blood_type_d A B C D E    WD
1   1            A 0 0 1 1 0 0.250
2   2            A 0 0 1 1 0 0.250
3   3            B 0 0 1 1 0 0.125
4   4            B 0 0 1 1 0 0.125
5   5           AB 0 0 1 1 0 0.125
6   6           AB 0 0 1 1 0 0.125
7   7            O 1 1 1 1 1 0.500
8   8            O 1 1 0 1 0 0.500

# function
soustraction.i=function(D,R,i,threshold){
  D=as.data.frame(D)
  R=as.data.frame(R)
  dif=map2_df(D, R[i,], `-`)
  dif[dif<0] = 0
  dif$mismatch=rowSums(dif)
  dif=dif[which(dif$mismatch <= threshold),]
  return(dif)
  
}

 soustraction.i(data_D[,3:7],data_R[,3:7],1,3)
# A tibble: 8 x 6
      A     B     C     D     E mismatch
  <dbl> <dbl> <dbl> <dbl> <dbl>    <dbl>
1     0     0     0     0     0        0
2     0     0     0     0     0        0
3     0     0     0     0     0        0
4     0     0     0     0     0        0
5     0     0     0     0     0        0
6     0     0     0     0     0        0
7     1     1     0     0     1        3
8     1     1     0     0     0        2

 

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

 soustraction.i(data_D[,3:7],data_R[,3:7],1,0)
# A tibble: 6 x 6
      A     B     C     D     E mismatch
  <dbl> <dbl> <dbl> <dbl> <dbl>    <dbl>
1     0     0     0     0     0        0
2     0     0     0     0     0        0
3     0     0     0     0     0        0
4     0     0     0     0     0        0
5     0     0     0     0     0        0
6     0     0     0     0     0        0
 

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

 # Desired output 
# A tibble: 8 x 6
      A     B     C     D     E mismatch
  <dbl> <dbl> <dbl> <dbl> <dbl>    <dbl>
1     0     0     0     0     0        0
2     0     0     0     0     0        0
3     0     0     0     0     0        0
4     0     0     0     0     0        0
5     0     0     0     0     0        0
6     0     0     0     0     0        0
7     1     1     0     0     1        NA
8     1     1     0     0     0        NA
 

Вот то, что я пробовал до сих пор, и это дает мне предупреждение и не делает правильные вещи

 soustraction.j=function(D,R,i,threshold){
  D=as.data.frame(D)
  R=as.data.frame(R)
  dif=map2_df(D, R[i,], `-`)
  dif[dif<0] = 0
  dif$mismatch=rowSums(dif)
  if(threshold==0){
    if(dif$mismatch > 0){
      dif$mismatch= NA
    }
  }else{
    dif=dif[which(dif$mismatch <= threshold),]
  }
 
  return(dif)
  
}
soustraction.j(data_D[,3:7],data_R[,3:7],1,0)
# A tibble: 8 x 6
      A     B     C     D     E mismatch
  <dbl> <dbl> <dbl> <dbl> <dbl>    <dbl>
1     0     0     0     0     0        0
2     0     0     0     0     0        0
3     0     0     0     0     0        0
4     0     0     0     0     0        0
5     0     0     0     0     0        0
6     0     0     0     0     0        0
7     1     1     0     0     1        3
8     1     1     0     0     0        2

#Warning message:
#In if (dif$mismatch > 0) { :
 # the condition has length > 1 and only the first element will be used
 

Заранее благодарим вас за помощь

Ответ №1:

Вот такое dplyr решение. Он должен работать для when threshold == 0 и обобщаться на другие пороговые значения:

 soustraction.i=function(D,R,i,threshold){
  D=as.data.frame(D)
  R=as.data.frame(R)
  dif=map2_df(D, R[i,], `-`)
  dif[dif<0] = 0
  dif$mismatch=rowSums(dif)
  dif <- dif %>%
    mutate(mismatch = case_when(mismatch > threshold ~ NA_real_,
                                TRUE ~ mismatch))
return(dif)
}
 

Выходной сигнал:

 soustraction.i(data_D[,3:7],data_R[,3:7],1,0)

# A tibble: 8 x 6
      A     B     C     D     E mismatch
  <dbl> <dbl> <dbl> <dbl> <dbl>    <dbl>
1     0     0     0     0     0        0
2     0     0     0     0     0        0
3     0     0     0     0     0        0
4     0     0     0     0     0        0
5     0     0     0     0     0        0
6     0     0     0     0     0        0
7     1     1     0     0     1       NA
8     1     1     0     0     0       NA

 

Редактировать

Вот один из примеров « dplyr переработанной» версии вашей функции

 soustraction.i <- function(D,R,i,threshold){
  D <- as_tibble(D)
  R <- as_tibble(R)
  dif <- map2_df(D, R[i,], `-`) %>%
    mutate(across(everything(), ~ifelse(.x < 0, 0, .x))) %>%
    rowwise() %>%
    mutate(mismatch = sum(c_across(everything())),
           mismatch = case_when(as.numeric(mismatch) > threshold ~ NA_real_,
                                TRUE ~ mismatch))
  return(dif)
}

 

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

1. Спасибо @latlio за ваш ответ! Это то, что я искал. Я ценю это.

Ответ №2:

Вместо того, чтобы брать подмножество строк, вы можете присвоить им значение NA where mismatch больше, чем threshold .

 soustraction.i=function(D,R,i,threshold){
  D=as.data.frame(D)
  R=as.data.frame(R)
  dif= purrr::map2_df(D, R[i,], `-`)
  dif[dif<0] = 0
  dif$mismatch=rowSums(dif)
  dif$mismatch[dif$mismatch > threshold] <- NA
  return(dif)
}
 

Вы можете проверить вывод :

 soustraction.i(data_D[,3:7],data_R[,3:7],1,3)
# A tibble: 8 x 6
#      A     B     C     D     E mismatch
#  <dbl> <dbl> <dbl> <dbl> <dbl>    <dbl>
#1     0     0     0     0     0        0
#2     0     0     0     0     0        0
#3     0     0     0     0     0        0
#4     0     0     0     0     0        0
#5     0     0     0     0     0        0
#6     0     0     0     0     0        0
#7     1     1     0     0     1        3
#8     1     1     0     0     0        2

soustraction.i(data_D[,3:7],data_R[,3:7],1,0)
# A tibble: 8 x 6
#      A     B     C     D     E mismatch
#  <dbl> <dbl> <dbl> <dbl> <dbl>    <dbl>
#1     0     0     0     0     0        0
#2     0     0     0     0     0        0
#3     0     0     0     0     0        0
#4     0     0     0     0     0        0
#5     0     0     0     0     0        0
#6     0     0     0     0     0        0
#7     1     1     0     0     1       NA
#8     1     1     0     0     0       NA