Вопрос по r – Заменить все 0 значений на NA

103

У меня есть датафрейм с некоторыми числовыми столбцами. Некоторая строка имеет значение 0, которое следует рассматривать как нулевое в статистическом анализе. Какой самый быстрый способ заменить все значение 0 на NULL в R?

Я не думаю, что вы хотите / можете заменить значениями NULL, но NA выполняет эту задачу в R lingo. Chase

Ваш Ответ

7   ответов
186

Замена всех нулей на NA:

df[df == 0] <- NA



Объяснение

1. НетNULL чем вы хотите заменить нули. Как говорится в?'NULL',

NULL представляет нулевой объект в R

который уникален и, я думаю, может рассматриваться как самый неинформативный и пустой объект.1 Тогда не удивительно, что

data.frame(x = c(1, NULL, 2))
#   x
# 1 1
# 2 2

То есть R не резервирует места для этого нулевого объекта.2 Между тем, глядя на?'NA' Мы видим, чт

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

Важно,NA имеет длину 1, так что R резервирует некоторое пространство для него. Например.

data.frame(x = c(1, NA, 2))
#    x
# 1  1
# 2 NA
# 3  2

Кроме того, структура фрейма данных требует, чтобы все столбцы имели одинаковое количество элементов, чтобы не было «дыр» (т. Е.,NULL значения)

Теперь вы можете заменить нули наNULL в кадре данных в смысле полного удаления всех строк, содержащих хотя бы один ноль. При использовании, например,var, cov, илиcor, это фактически эквивалентно первой замене нулей наNA и установка значенияuse как"complete.obs". Однако, как правило, это неудовлетворительно, так как приводит к дополнительной потере информации.

2. Вместо запуска какого-то цикла, в решении, которое я использую,df == 0 векторизация.df == 0 возвращает (попробуйте) матрицу того же размера, что иdf, с записямиTRUE а такжеFALSE. Кроме того, нам также разрешено передавать эту матрицу в подмножество[...] (видеть?'['). Наконец, пока результатdf[df == 0] интуитивно понятен, может показаться странным, чтоdf[df == 0] <- NA дает желаемый эффект. Оператор присваивания<- действительно не всегда такой умный и не работает таким образом с некоторыми другими объектами, но он работает с фреймами данных; видеть?'<-'.


1 Пустое множество в теории множеств кажется как-то связанным.
2 Еще одно сходство с теорией множеств: пустое множество является подмножеством каждого множества, но мы не оставляем для него места.

Какой будет эквивалентный синтаксис для объекта data.table? itpetersen
Я вижу, что вы получили много голосов, но не думаю, что это надлежащим образом охватывает крайние случаи нечисловых столбцов со значениями "0", для которых не было задано значение <NA>. 42-
22

[<- функция:

Образец фрейма данныхdat (бесстыдно скопировано с ответа Чейза):

dat

  x y
1 0 2
2 1 2
3 1 1
4 2 1
5 0 0

Нули можно заменить наNA посредствомis.na<- функция:

is.na(dat) <- !dat


dat

   x  y
1 NA  2
2  1  2
3  1  1
4  2  1
5 NA NA
14
#Sample data
set.seed(1)
dat <- data.frame(x = sample(0:2, 5, TRUE), y = sample(0:2, 5, TRUE))
#-----
  x y
1 0 2
2 1 2
3 1 1
4 2 1
5 0 0

#replace zeros with NA
dat[dat==0] <- NA
#-----
   x  y
1 NA  2
2  1  2
3  1  1
4  2  1
5 NA NA
27

что ваш data.frame представляет собой смесь разных типов данных, и не все столбцы нужно изменять.

чтобы изменить только столбцы с 12 по 18 (из общего числа 21), просто сделайте это

df[, 12:18][df[, 12:18] == 0] <- NA
12

и поскольку данное решение data.frame не работает с data.table, я предлагаю решение ниже.

В основном используйте:= оператор ->DT[x == 0, x := NA]

library("data.table")

status = as.data.table(occupationalStatus)

head(status, 10)
    origin destination  N
 1:      1           1 50
 2:      2           1 16
 3:      3           1 12
 4:      4           1 11
 5:      5           1  2
 6:      6           1 12
 7:      7           1  0
 8:      8           1  0
 9:      1           2 19
10:      2           2 40


status[N == 0, N := NA]

head(status, 10)
    origin destination  N
 1:      1           1 50
 2:      2           1 16
 3:      3           1 12
 4:      4           1 11
 5:      5           1  2
 6:      6           1 12
 7:      7           1 NA
 8:      8           1 NA
 9:      1           2 19
10:      2           2 40
Илиfor (j in names(DT)); set(DT,which(DT[[j]] == 0),j,NA). ВидетьВо для более подробного обсуждения использования data.table для поиска и замены значений. JWilliman
10

dplyr::na_if() это вариант:


df <- data_frame(col1 = c(1, 2, 3, 0),
                 col2 = c(0, 2, 3, 4),
                 col3 = c(1, 0, 3, 0),
                 col4 = c('a', 'b', 'c', 'd'))

na_if(df, 0)
# A tibble: 4 x 4
   col1  col2  col3 col4 
  <dbl> <dbl> <dbl> <chr>
1     1    NA     1 a    
2     2     2    NA b    
3     3     3     3 c    
4    NA     4    NA d
4

Ты можешь заменить0 сNA только в числовых полях (т.е. исключая такие вещи, как факторы), но работает по столбцам:

col[col == 0 & is.numeric(col)] <- NA

С помощью функции вы можете применить ее ко всему фрейму данных:

changetoNA <- function(colnum,df) {
    col <- df[,colnum]
    if (is.numeric(col)) {  #edit: verifying column is numeric
        col[col == -1 & is.numeric(col)] <- NA
    }
    return(col)
}
df <- data.frame(sapply(1:5, changetoNA, df))

Хотя ты мог бы заменить1:5 с количеством столбцов в вашем фрейме данных или с1:ncol(df).

Я не уверен, что это правильное решение. Как насчет колонок 6 и более. Они будут сокращены. userJT
Вот почему я предложил заменить1:5 с1:ncol(df) в конце. Я не хотел делать уравнение слишком сложным или трудным для чтения. Alium Britt
но что если в столбцах 6 и 7 - тип данных char, и замена не должна производиться. В моей задаче мне нужна замена только в столбцах с 12 по 15, но весь df имеет 21 столбец (многие не должны касаться). userJT
Для вашего фрейма данных вы можете просто изменить1:5 на номера столбцов, которые вы хотите изменить, как12:15, но если вы хотите подтвердить, что это повлияет только на числовые столбцы, просто заключите вторую строку функции в оператор if, например так:if (is.numeric(col)) { col[col == -1 & is.numeric(col)] <- NA }. Alium Britt

Похожие вопросы