Укажите различные типы пропущенных значений (NAs)

Мне интересно указать типы пропущенных значений. У меня есть данные, которые имеют разные типы отсутствующих, и я пытаюсь закодировать эти значения как отсутствующие в R, но я ищу решение, при котором я все еще могу различать их.

Скажем, у меня есть данные, которые выглядят так,

set.seed(667) 
df <- data.frame(a = sample(c("Don't know/Not sure","Unknown","Refused","Blue", "Red", "Green"),  20, rep=TRUE), b = sample(c(1, 2, 3, 77, 88, 99),  10, rep=TRUE), f = round(rnorm(n=10, mean=.90, sd=.08), digits = 2), g = sample(c("C","M","Y","K"),  10, rep=TRUE) ); df
#                      a  b    f g
# 1              Unknown  2 0.78 M
# 2              Refused  2 0.87 M
# 3                  Red 77 0.82 Y
# 4                  Red 99 0.78 Y
# 5                Green 77 0.97 M
# 6                Green  3 0.99 K
# 7                  Red  3 0.99 Y
# 8                Green 88 0.84 C
# 9              Unknown 99 1.08 M
# 10             Refused 99 0.81 C
# 11                Blue  2 0.78 M
# 12               Green  2 0.87 M
# 13                Blue 77 0.82 Y
# 14 Don't know/Not sure 99 0.78 Y
# 15             Unknown 77 0.97 M
# 16             Refused  3 0.99 K
# 17                Blue  3 0.99 Y
# 18               Green 88 0.84 C
# 19             Refused 99 1.08 M
# 20                 Red 99 0.81 C

Если я сейчас сделаю две таблицы, мои недостающие значения ("Don't know/Not sure","Unknown","Refused" и 77, 88, 99) будут включены как обычные данные,

table(df$a,df$g)
#                     C K M Y
# Blue                0 0 1 2
# Don't know/Not sure 0 0 0 1
# Green               2 1 2 0
# Red                 1 0 0 3
# Refused             1 1 2 0
# Unknown             0 0 3 0

а также

table(df$b,df$g)
#    C K M Y
# 2  0 0 4 0
# 3  0 2 0 2
# 77 0 0 2 2
# 88 2 0 0 0
# 99 2 0 2 2

Теперь я перекодирую три уровня факторов "Don't know/Not sure","Unknown","Refused" в <NA>

is.na(df[,c("a")]) <- df[,c("a")]=="Don't know/Not sure"|df[,c("a")]=="Unknown"|df[,c("a")]=="Refused"

и удалите пустые уровни

df$a <- factor(df$a) 

и то же самое с числовыми значениями 77, 88, и 99

is.na(df) <- df=="77"|df=="88"|df=="99"

table(df$a, df$g, useNA = "always")       
#       C K M Y <NA>
# Blue  0 0 1 2    0
# Green 2 1 2 0    0
# Red   1 0 0 3    0
# <NA>  1 1 5 1    0

table(df$b,df$g, useNA = "always")
#      C K M Y <NA>
# 2    0 0 4 0    0
# 3    0 2 0 2    0
# <NA> 4 0 4 4    0

Теперь недостающие категории перекодированы в NA, но все они собраны вместе. Есть ли способ перекодировать что-то как отсутствующее, но сохранить исходные значения? Я хочу, чтобы R передавал "Don't know/Not sure","Unknown","Refused" и 77, 88, 99 как отсутствующие, но я хочу, чтобы информация в переменной по-прежнему оставалась.


person Eric Fail    schedule 18.04.2013    source источник
comment
Как насчет добавления еще одного столбца к df с именем isNA, который будет оставаться верным, если значение отсутствует? или столбец isNA может содержать непосредственно NA и 0. Это зависит от остальной части вашего кода.   -  person Nishanth    schedule 18.04.2013
comment
Это могло бы сработать, но это скорее обходной путь, чем решение, которое будет работать без проблем с остальной частью моего кода - как вы также указываете. Не могли бы вы продемонстрировать это на примере?   -  person Eric Fail    schedule 18.04.2013
comment
Трудно предсказать влияние на остальную часть кода. может быть, вы можете написать свой собственный my.table, который использует my.is.na, который возвращает TRUE для "Не знаю / Не уверен", "Неизвестно", "Отказано"   -  person Nishanth    schedule 18.04.2013
comment
Похоже, вы предоставили нам обобщенные данные. У вас есть данные в формате, который на шаг раньше этого? Если так, то это просто вопрос факторинга.   -  person Brandon Bertelsen    schedule 21.04.2013
comment
@BrandonBertelsen, спасибо за ваш вопрос (и ваш ответ). Приведенные мною фиктивные данные довольно близки к тому, как выглядят мои настоящие данные. Как я уже упоминал в мой комментарий к @ Maxim.KI мог быть немного точнее о переменной a, но помимо этого данные, которые я предоставил в вопросе, довольно близки к тому, как выглядят мои настоящие данные.   -  person Eric Fail    schedule 23.04.2013


Ответы (3)


Насколько мне известно, базовый R не имеет встроенного способа обработки различных NA типов. (редактор: Имеется: NA_integer_, NA_real_, NA_complex_ и NA_character. См. ?base::NA.)

Один из вариантов - использовать пакет, который делает это, например "memisc < / а> ". Это немного лишняя работа, но, похоже, она делает то, что вы ищете.

Вот пример:

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

set.seed(667) 
df <- data.frame(a = sample(c("Don't know/Not sure", "Unknown", 
                              "Refused", "Blue", "Red", "Green"),
                            20, replace = TRUE), 
                 b = sample(c(1, 2, 3, 77, 88, 99), 10, 
                            replace = TRUE), 
                 f = round(rnorm(n = 10, mean = .90, sd = .08), 
                           digits = 2), 
                 g = sample(c("C", "M", "Y", "K"), 10, 
                            replace = TRUE))
df2 <- df

Разложим на множители переменную "а":

df2$a <- factor(df2$a, 
                levels = c("Blue", "Red", "Green", 
                           "Don't know/Not sure",
                           "Refused", "Unknown"),
                labels = c(1, 2, 3, 77, 88, 99))

Загрузите библиотеку memisc:

library(memisc)

Теперь преобразуйте переменные «a» и «b» в items в «memisc»:

df2$a <- as.item(as.character(df2$a), 
                  labels = structure(c(1, 2, 3, 77, 88, 99),
                                     names = c("Blue", "Red", "Green", 
                                               "Don't know/Not sure",
                                               "Refused", "Unknown")),
                  missing.values = c(77, 88, 99))
df2$b <- as.item(df2$b, 
                 labels = c(1, 2, 3, 77, 88, 99), 
                 missing.values = c(77, 88, 99))

Благодаря этому у нас появился новый тип данных. Сравните следующее:

as.factor(df2$a)
#  [1] <NA>  <NA>  Red   Red   Green Green Red   Green <NA>  <NA>  Blue 
# [12] Green Blue  <NA>  <NA>  <NA>  Blue  Green <NA>  Red  
# Levels: Blue Red Green
as.factor(include.missings(df2$a))
#  [1] *Unknown             *Refused             Red                 
#  [4] Red                  Green                Green               
#  [7] Red                  Green                *Unknown            
# [10] *Refused             Blue                 Green               
# [13] Blue                 *Don't know/Not sure *Unknown            
# [16] *Refused             Blue                 Green               
# [19] *Refused             Red                 
# Levels: Blue Red Green *Don't know/Not sure *Refused *Unknown

Мы можем использовать эту информацию для создания таблиц, ведущих себя так, как вы описываете, с сохранением всей исходной информации.

table(as.factor(include.missings(df2$a)), df2$g)
#                       
#                        C K M Y
#   Blue                 0 0 1 2
#   Red                  1 0 0 3
#   Green                2 1 2 0
#   *Don't know/Not sure 0 0 0 1
#   *Refused             1 1 2 0
#   *Unknown             0 0 3 0
table(as.factor(df2$a), df2$g)
#        
#         C K M Y
#   Blue  0 0 1 2
#   Red   1 0 0 3
#   Green 2 1 2 0
table(as.factor(df2$a), df2$g, useNA="always")
#        
#         C K M Y <NA>
#   Blue  0 0 1 2    0
#   Red   1 0 0 3    0
#   Green 2 1 2 0    0
#   <NA>  1 1 5 1    0

Таблицы для числового столбца с отсутствующими данными ведут себя так же.

table(as.factor(include.missings(df2$b)), df2$g)
#      
#       C K M Y
#   1   0 0 0 0
#   2   0 0 4 0
#   3   0 2 0 2
#   *77 0 0 2 2
#   *88 2 0 0 0
#   *99 2 0 2 2
table(as.factor(df2$b), df2$g, useNA="always")
#       
#        C K M Y <NA>
#   1    0 0 0 0    0
#   2    0 0 4 0    0
#   3    0 2 0 2    0
#   <NA> 4 0 4 4    0

В качестве бонуса вы получаете возможность генерировать красивые codebook:

> codebook(df2$a)
========================================================================

   df2$a

------------------------------------------------------------------------

   Storage mode: character
   Measurement: nominal
   Missing values: 77, 88, 99

            Values and labels    N    Percent 

    1   'Blue'                   3   25.0 15.0
    2   'Red'                    4   33.3 20.0
    3   'Green'                  5   41.7 25.0
   77 M 'Don't know/Not sure'    1         5.0
   88 M 'Refused'                4        20.0
   99 M 'Unknown'                3        15.0

Однако я также предлагаю вам прочитать комментарий от @ Максим.К о том, что на самом деле составляет недостающие значения.

person A5C1D2H2I1M1N2O1R2T1    schedule 21.04.2013
comment
+1 очень хороший развернутый ответ! Мне нравится "*" в названиях, когда include.missings :) - person agstudy; 21.04.2013
comment
Спасибо за хороший подробный ответ, как также отмечает @agstudy. - person Eric Fail; 23.04.2013
comment
+1 действительно подробно, красиво. У R есть способ обрабатывать различные типы NA, но я не знаю, сможете ли вы его использовать. Это должно быть сделано, чтобы иметь возможность делать class( c(1,2,NA) ), который равен "numeric", и class( c("a","b",NA) ), который равен "character"? - person Simon O'Hanlon; 23.04.2013
comment
Какие еще пакеты позволяют одновременно использовать разные виды промахов? У меня есть набор данных со многими переменными, некоторыми числовыми, некоторыми датами, и я хочу закодировать три разных типа пропусков: ошибки, неизвестные и пропуски, созданные из-за изменения формы данных. - person skan; 01.05.2017

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

df <- transform(df,b.na = ifelse(b %in% c('77','88','99'),NA,b))
df <- transform(df,a.na = ifelse(a %in% 
                        c("Don't know/Not sure","Unknown","Refused"),NA,a))

Тогда вы можете сделать что-то вроде этого:

   table(df$b.na , df$g)
    C K M Y
  2 0 0 4 0
  3 0 2 0 2

Другой вариант без создания новых столбцов - использовать такой вариант exclude, чтобы установить нежелательные значения в NULL (отличные от отсутствующих значений).

table(df$a,df$g,
      exclude=c('77','88','99',"Don't know/Not sure","Unknown","Refused")) 
       C K M Y
  Blue  0 0 1 2
  Green 2 1 2 0
  Red   1 0 0 3

Вы можете определить некоторые глобальные константы (даже если это не рекомендуется), чтобы сгруппировать ваши «недостающие значения» и использовать их в остальной части вашей программы. Что-то вроде этого :

B_MISSING <- c('77','88','99')
A_MISSING <- c("Don't know/Not sure","Unknown","Refused")
person agstudy    schedule 18.04.2013
comment
Спасибо, что ответили на мой вопрос. Я не знал об опции exclude. Это интересное решение. Я все еще несколько удивлен, что в R есть только одна категория пропущенных значений. - person Eric Fail; 18.04.2013
comment
@EricFail R имеет одно отсутствующее, в основном логическое значение, но также может иметь разные типы: NA_integer_, NA_real_, NA_complex_ and NA_character_. Вы можете увидеть мою редакцию глобального решения. - person agstudy; 18.04.2013
comment
Строго говоря, это (не все) упущения. Не знаю - это не пропущенная, это допустимая категория ответов, и во многих случаях ее следует рассматривать как таковую. Refused также содержит информацию, тогда как Unknown, вероятно, действительно отсутствует. Я бы просто создал дополнительный столбец с этими тремя подкатегориями и ссылался на них всякий раз, когда мне было нужно, используя обычную NA для статистических методов, которые не различаются. - person Maxim.K; 18.04.2013
comment
@ Maxim.K, ваш комментарий заставил меня понять, что я мог бы быть более точным в своем вопросе. Переменная a в моем примере должна была быть больше похожей на эту c("Unknown", "Refused", 1, 1, 2, 2, 1, 2, "Unknown", "Refused", 3, 2, 3, "Don't know/Not sure", "Unknown", "Refused", 3, 2, "Refused", 1), и меня интересует сохранение a таким образом, чтобы я мог ее резюмировать, но не теряя различия между «Не знаю / Не уверен», Неизвестно, Отказано. Имеет ли это смысл? - person Eric Fail; 23.04.2013
comment
@agstudy, что касается глобальных констант, будет ли это частью моего .Rprofile? - person Eric Fail; 23.04.2013
comment
@EricFail, должна ли переменная быть числовой? категоричный? фактор? - person A5C1D2H2I1M1N2O1R2T1; 23.04.2013
comment
@AnandaMahto, в примере в исходный вопрос a является фактором. В комментарии выше это символьная переменная. . Это может быть что угодно, если это поможет ответить на вопрос. - person Eric Fail; 23.04.2013
comment
@EricFail, в этом случае вы можете попробовать изменить то, чем я поделился, следующим образом: df2$a <- factor(df2$a, levels = c(1, 2, 3, "Don't know/Not sure", "Refused", "Unknown"), labels = c(1, 2, 3, "Don't know/Not sure", "Refused", "Unknown")); df2$a <- as.item(as.character(df2$a), labels = structure(c(1, 2, 3, "Don't know/Not sure", "Refused", "Unknown"), names = c(1, 2, 3, "Don't know/Not sure", "Refused", "Unknown")), missing.values = c("Don't know/Not sure", "Refused", "Unknown")). Надеюсь, это поможет. - person A5C1D2H2I1M1N2O1R2T1; 23.04.2013

Если вы хотите придерживаться числовых значений, тогда NA, Inf, -Inf и NaN можно использовать для разных пропущенных значений. Затем вы можете использовать is.finite, чтобы отличить их от нормальных значений:

x <- c(NA, Inf, -Inf, NaN, 1)
is.finite(x)
## [1] FALSE FALSE FALSE FALSE  TRUE

is.infinite, is.nan и is.na также полезны здесь.

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

person G. Grothendieck    schedule 24.04.2013