Как мне исправить эту проблему «Ошибка в .subset 2 (x, i, exact = exact)» в R?

#r #matrix

#r #матрица

Вопрос:

Я использую следующий фрейм данных в R:

 ID <- c(LETTERS[1:10])
GLUC <- c(88,NA,110,NA,90,88,120,110,NA,90)
TGL <- c(NA,150,NA,200,210,NA,164,170,190,NA)
HDL <- c(32,60,NA,65,NA,32,NA,70,NA,75)
LDL <- c(99,NA,120,165,150,210,NA,188,190,NA)

patient_num <- data.frame(ID,GLUC,TGL,HDL,LDL)
  

И я хочу создать матрицу, в которой в качестве имен строк указаны GLUC, TGL, HDL и LDL, а в качестве имен столбцов — среднее, медианное, sd, n и n_miss. Когда я ввожу следующий код:

   r <- c(mean(patient_num[[varname]],na.rm=TRUE), 
    median(patient_num[[varname]],na.rm=TRUE), 
    sd(patient_num[[varname]],na.rm=TRUE),
    sum(!is.na(patient_num[[varname]])),
    sum(is.na(patient_num[[varname]]))
    )
  if (length(varname) == 1){
    r <- matrix(r,nrow=T)
  } else{
    for (index in 2:length(varname)){
      oneRow = table1(patient_num,varname[[index]])
      r <- rbind(r,oneRow)
    }
  }
  rownames(r) <- varname
  colnames(r) <- c("mean","median","sd","n","n_miss")
  return(r)
}

table1(patient_num,c("GLUC","TGL","HDL","LDL")) 
  

Я получаю сообщение об ошибке:

Ошибка в .subset 2 (x, i, exact = exact): сбой рекурсивной индексации на уровне 2

Кажется, не могу понять, что не так

Ответ №1:

Есть более простое решение, использующее sapply() from base R :

 new_df <- sapply(patient_num, function(x) list(
  mean = mean(x, na.rm = T),
  sd = sd(x, na.rm = T),
  n = sum(!is.na(x)),
  is_na = sum(is.na(x))))

t(new_df)

#>     mean     sd       n  is_na
#>ID   NA       NA       10 0    
#>GLUC 99.42857 13.45185 7  3    
#>TGL  180.6667 23.0362  6  4    
#>HDL  55.66667 19.00175 6  4    
#>LDL  160.2857 40.06126 7  3 
  

Если вам нужно только количество записей, отличных от NA, в каждой строке, вы можете просто удалить ID из patient_num и запустить тот же код.

Обратите внимание, что вы можете захотеть преобразовать new_df обратно в a data.frame .

Ответ №2:

Вы можете выбирать только один столбец за раз, используя [[ .

Вот альтернативный способ с использованием dplyr функций.

 library(dplyr)

table1 <- function(data, varname) {

  data %>%
    select(all_of(varname)) %>%
    tidyr::pivot_longer(cols = everything()) %>%
    group_by(name) %>%
    summarise(mean = mean(value, na.rm = TRUE), 
              median = median(value, na.rm = TRUE), 
              sd = sd(value, na.rm = TRUE), 
              n = sum(!is.na(value)), 
              n_miss = sum(is.na(value)))
}

table1(patient_num,c("GLUC","TGL","HDL","LDL")) 

# A tibble: 4 x 6
#  name   mean median    sd     n n_miss
#  <chr> <dbl>  <dbl> <dbl> <int>  <int>
#1 GLUC   99.4   90    13.5     7      3
#2 HDL    55.7   62.5  19.0     6      4
#3 LDL   160.   165    40.1     7      3
#4 TGL   181.   180    23.0     6      4