Предложение для функции R - PullRequest
0 голосов
/ 26 октября 2019

Я только начинаю в R и пытаюсь написать функцию, которая может дать мне сводку по NA по столбцам в данных. У меня есть пара вопросов:

  1. Если я передам список, как функция сможет выбрать свое имя? Например, если я передам 'listA', функция должна вернуть listA с количеством NA внизу. В настоящее время он возвращает «х» и количество под-NA. Например:

     E <- c(NA,1,2,3); na_cols_summary(E)
    

    дает

     $x
     [1] NA
    
  2. Может кто-нибудь подсказать, как я могу использовать функцию из семейства 'apply', чтобы сделать функцию более элегантной.

  3. У нас есть пакет / функция с аналогичной функциональностью?

    ###Sample Data
    A <- c(1:10)
    B <- c(11:20)
    C <- c(21:30)
    D <- c(31:40)
    df <- data.frame(A, B, C, D)
    df <-
      as.data.frame(lapply(df, function(cc)
        cc[sample(
          c(TRUE, NA),
          prob = c(0.85, 0.15),
          size = length(cc),
          replace = TRUE
        )]))
    
    
    
    na_cols_summary <- function(x) {
       x <- as.data.frame(x)
       y <- colSums(is.na(x))
       y <- y[y != 0]
       nalis <- list()
       i <- 1
       for (z in names(y)) {
            nalis[i] <- list(x[is.na(x[, z]), ])
            i <- i + 1
        }
       names(nalis) <- names(y)
       return(nalis)
       }
    df_na <- na_cols_summary(df)
    
    df_na
    $A
       A  B  C  D
    3  NA NA 23 33
    4  NA 14 24 34
    10 NA 20 30 40
    
    $B
       A  B  C  D
    3 NA NA 23 33
    8  8 NA 28 38
    

1 Ответ

1 голос
/ 26 октября 2019

Вы можете использовать lapply.

Это имитирует вашу функцию.

lapply(df2 <- df1[colSums(is.na(df1)) > 0], function(x) df2[is.na(x), ])
# $A
#    A  B  C
# 1 NA 11 NA
# 2 NA 12 22
# 
# $B
#   A  B  C
# 3 3 NA NA
# 6 6 NA 26
# 7 7 NA 27
# 
# $C
#    A  B  C
# 1 NA 11 NA
# 3  3 NA NA
# 4  4 14 NA
# 8  8 18 NA

Чтобы получить не только отсутствующие столбцы в выводе, просто выполните lapply(df1, function(x) df1[is.na(x), ]).

Чтобы получить имя вашего объекта, вы можетеиспользуйте deparse(substitute(.))

f <- function(x) deparse(substitute(x))
f(E)
# [1] "E"

Чтобы объединить это в функцию, вы можете сделать:

na_cols_summary2 <- function(x) {
  stopifnot(is.data.frame(x) | is.vector(x))
  if (!any(is.na(x))) {
    return(message("No missings found.\n"))
  }
  if (is.data.frame(x)) {
    res <- lapply(x, function(i) x[is.na(i), ])
    res <- res[lapply(res, nrow) > 0]
  } else {
    res <- setNames(as.data.frame(x), deparse(substitute(x)))
  } 
  return(res)
}

Использование

na_cols_summary2(df1)
# $A
#    A  B  C  D
# 1 NA 11 NA 31
# 2 NA 12 22 32
# 
# $B
#   A  B  C  D
# 3 3 NA NA 33
# 6 6 NA 26 36
# 7 7 NA 27 37
# 
# $C
#    A  B  C  D
# 1 NA 11 NA 31
# 3  3 NA NA 33
# 4  4 14 NA 34
# 8  8 18 NA 38

na_cols_summary2(E)
#    E
# 1 NA
# 2  1
# 3  2
# 4  3

na_cols_summary2(E2)
# No missings found.

na_cols_summary2(matrix(0, 4))
# Error in na_cols_summary2(matrix(0, 4)) : 
#  is.data.frame(x) | is.vector(x) is not TRUE 

Данные

df1 <- structure(list(A = c(NA, NA, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L), 
    B = c(11L, 12L, NA, 14L, 15L, NA, NA, 18L, 19L, 20L), C = c(NA, 
    22L, NA, NA, 25L, 26L, 27L, NA, 29L, 30L), D = c(31, 32, 
    33, 34, 35, 36, 37, 38, 39, 40)), row.names = c(NA, -10L), class = "data.frame")

E <- c(NA, 1, 2, 3)
E2 <- 1:4
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...