Замініть всі значення 0 на NA


145

У мене є кадр даних з деякими числовими стовпцями. Деякий рядок має значення 0, яке слід вважати нульовим у статистичному аналізі. Який найшвидший спосіб замінити всі значення 0 на NULL в R?


17
Я не думаю, що ви хочете / можете замінити значеннями NULL, але NA виконує цю мету в R lingo.
Чейз

Відповіді:


244

Заміна всіх нулів на 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 може бути примушений до будь-якого іншого типу вектора, крім сировини.

Важливо, що 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 Ще одна схожість з теорією множин: порожній набір - це підмножина кожного набору, але ми не залишаємо для нього жодного місця.


3
Який би еквівалентний синтаксис був би для об'єкта data.table?
itpetersen

6
Я бачу, що ви отримали багато голосів, але не вважайте, що це належним чином охоплює крайові випадки нечислових стовпців зі значеннями "0", які не вимагали встановлювати <NA>.
IRTFM

33

Дозвольте припустити, що ваш data.frame - це сукупність різних типів даних, і не всі стовпці потрібно змінювати.

щоб змінити лише стовпці 12-18 (всього 21), просто зробіть це

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

Це працює для мене, поки прийнятої відповіді немає
Патрік Куломбе

23

Альтернативний спосіб без [<-функції:

Зразок кадру даних dat(безсоромно скопійований з відповіді @ Chase):

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

22

dplyr::na_if() є варіант:

library(dplyr)  

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

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

12

Оскільки хтось запитав про версію Data.Table цього і тому, що дане рішення 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

2
Або for (j in names(DT)); set(DT,which(DT[[j]] == 0),j,NA). Дивіться тут для більш детального обговорення використання data.table для пошуку та заміни значень.
JWilliman

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 та більше. Вони будуть розрізані.
користувачJT

Ось чому я запропонував замінити 1:5з 1:ncol(df)в кінці. Я не хотів робити рівняння надто складним чи важким для читання.
Аліум Брітт

але що робити, якщо у стовпцях 6 та 7 - тип даних є символом та заміни не слід робити. У моїй проблемі мені потрібна заміна лише у стовпцях 12-15, але весь df має 21 стовпчик (багатьох не слід торкатися взагалі).
користувачJT

Для вашого фрейму даних , ви можете просто змінити 1:5на номери стовпців , які ви хочете змінилися, як 12:15, але якщо ви хочете , щоб підтвердити , що він буде впливати тільки на стовпчики чисел , то просто загорнути другий рядок функції в , якщо заяву, як це: if (is.numeric(col)) { col[col == -1 & is.numeric(col)] <- NA }.
Аліум Брітт

0

Якщо хтось сюди приїжджає через Google, шукаючи навпаки (тобто як замінити всі NA в файлі data.frame на 0), відповідь

df[is.na(df)] <- 0

АБО

Використання dplyr / tidyverse

library(dplyr)
mtcars %>% replace(is.na(.), 0)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.