R - пользовательская функция для замены пропущенных значений - PullRequest
0 голосов
/ 11 марта 2020

Я пытаюсь создать пользовательскую функцию для замены пропущенных значений в каждой переменной с использованием указанных c вероятностей.

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

Я не получаю какое-то конкретное сообщение об ошибке, которое так озадачило почему не работает.

Мои данные:

library(dplyr)
library(glue)

structure(list(id = c("395891", "373742", "316241", "282072", 
"341331", "251761", "154591", "125051", "095361", "141822", "281411", 
"31571", "165191", "03212", "08091", "26172", "135561", "164331", 
"344511", "37352"), ph201_01 = c(1L, NA, 1L, 1L, NA, 1L, 1L, 
NA, NA, NA, 1L, NA, NA, 1L, NA, 1L, NA, NA, 1L, NA), ph201_02 = c(NA_integer_, 
NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_, 
NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_, 
NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_, 
NA_integer_, NA_integer_, NA_integer_, NA_integer_), ph201_03 = c(NA, 
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, 1L, NA, NA, NA, 
NA, NA, NA), ph201_04 = c(NA_integer_, NA_integer_, NA_integer_, 
NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_, 
NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_, 
NA_integer_, NA_integer_, NA_integer_, NA_integer_, NA_integer_, 
NA_integer_, NA_integer_)), class = c("tbl_df", "tbl", "data.frame"
), row.names = c(NA, -20L))

Мой код:

# Create user-defined function
create_mock_vars = function(var) {

  # get prevalence
  prev = round(sum(mydata[[var]], na.rm=TRUE)/nrow(mydata), 2)
  print(glue("Prevalence of {var} is {prev}."))

  mydata[[var]][is.na(mydata[[var]])] = sample(0:1, size=sum(is.na(mydata[[var]])), replace=TRUE, prob=c(prev, 1-prev))

  return(mydata)
}

# Get list of variable names I want to impute
myvarnames = names(mydata[,-1])

# Apply my function
sapply(myvarnames, create_mock_vars)

glimpse(mydata)

Ответы [ 3 ]

1 голос
/ 11 марта 2020

Вы можете создать пользовательскую функцию как:

create_mock_vars = function(x) {
   prev <- sum(x, na.rm=TRUE)/length(x)
   x[is.na(x)] <- sample(0:1, size = sum(is.na(x)), replace=TRUE, 
                         prob= c(prev, 1-prev))
   return(x)
}

и использовать lapply, чтобы применить ее к каждому myvarnames столбцу

mydata[myvarnames] <- lapply(mydata[myvarnames], create_mock_vars)
0 голосов
/ 11 марта 2020

Мне удалось решить эту проблему, но без создания пользовательской функции. Тем не менее, было бы замечательно, если бы кто-то мог помочь мне выяснить, что я сделал не так для дальнейшего использования?

myvarnames = names(mydata[,-1])

for (i in myvarnames) {
  prev = round(sum(mydata[[i]], na.rm=TRUE)/nrow(mydata), 2) # prevalence of deficit
  mydata[[i]][is.na(mydata[[i]])] = sample(0:1, size=sum(is.na(mydata[[i]])), replace=TRUE, prob=c(prev, 1-prev))
}

glimpse(mydata)
0 голосов
/ 11 марта 2020

Не совсем уверен, что вы имеете в виду, так что вот два решения Base R:

df1 <- data.frame(lapply(df,
                         function(x) {
                           if (is.numeric(x) & sum(is.na(x)) == length(x)) {
                             NA_integer_
                           } else if (is.numeric(x)) {
                             ifelse(is.na(x), sum(x, na.rm = TRUE) / length(x), x)
                           } else{
                             ifelse(is.na(x), na.omit(x)[cumsum(!is.na(x))], x)
                           }
                         }))

df2 <- data.frame(lapply(df,
                        function(x) {
                          if (is.numeric(x)) {
                            ifelse(sum(is.na(x)) == length(x), 1, 
                                   ifelse(sum(is.na(x)) != length(x),
                                          sum(x, na.rm = TRUE) / length(x), x))
                          } else{
                            ifelse(is.na(x), na.omit(x)[cumsum(!is.na(x))], x)
                          }
                        }))

Данные:

df <- structure(
  list(
    id = c("395891", "373742", "316241", "282072",
           "341331", "251761"),
    ph201_01 = c(1L, NA, 1L, 1L, NA, 1L),
    ph201_02 = c(
      NA_integer_,
      NA_integer_,
      NA_integer_,
      NA_integer_,
      NA_integer_,
      NA_integer_
    ),
    ph201_03 = c(
      NA_integer_,
      NA_integer_,
      NA_integer_,
      NA_integer_,
      NA_integer_,
      NA_integer_
    ),
    ph201_04 = c(
      NA_integer_,
      NA_integer_,
      NA_integer_,
      NA_integer_,
      NA_integer_,
      NA_integer_
    )
  ),
  class = c("tbl_df",
            "tbl", "data.frame"),
  row.names = c(NA, -6L)
)
...