У меня есть фреймворк с несколькими числовыми столбцами. Некоторая строка имеет значение 0, которое при статистическом анализе следует рассматривать как нулевое. Каков самый быстрый способ заменить все значения 0 на NULL в R?
Я не думаю, что вы хотите / можете заменить значения NULL, но NA служит этой цели в R lingo.
Чейз
Ответы:
260
Замена всех нулей на 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 07
6
Я вижу, что вы получили много голосов, но не думаю, что это должным образом покрывает крайние случаи нечисловых столбцов со значениями «0», которые не запрашивались для установки в <NA>.
IRTFM
38
Позвольте предположить, что ваш data.frame представляет собой смесь разных типов данных, и не все столбцы нужно изменять.
чтобы изменить только столбцы с 12 по 18 (из всего 21), просто сделайте это
#Sample data
set.seed(1)
dat <- data.frame(x = sample(0:2, 5, TRUE), y = sample(0:2, 5, TRUE))
#-----
x y
102212311421500#replace zeros with NA
dat[dat==0] <- NA#-----
x y
1NA22123114215NANA
Или 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 и больше. Их порежут.
userJT
Вот почему я предложил заменить 1:5с 1:ncol(df)в конце. Я не хотел делать уравнение слишком сложным или трудным для чтения.
Alium Britt
но что, если в столбцах 6 и 7 - тип данных char и замену производить не следует. В моей проблеме мне нужна замена только в столбцах с 12 по 15, но весь df имеет 21 столбец (многие вообще нельзя трогать).
userJT
Для вашего фрейма данных , вы можете просто изменить 1:5на номера столбцов , которые вы хотите изменились, как 12:15, но если вы хотите , чтобы подтвердить , что он будет воздействовать только на числовые столбцы , то просто завернуть вторую строчку функции в , если заявление, как это: if (is.numeric(col)) { col[col == -1 & is.numeric(col)] <- NA }.
Alium Britt
1
Если кто-то прибывает сюда через Google и ищет обратное (например, как заменить все NA в data.frame на 0), ответ будет
Ответы:
Замена всех нулей на NA:
df[df == 0] <- NA
Объяснение
1. Это не
NULL
то, чем вам следует заменять нули. Как говорится в?'NULL'
,который уникален и, я думаю, может рассматриваться как самый неинформативный и пустой объект. 1 Тогда неудивительно, что
data.frame(x = c(1, NULL, 2)) # x # 1 1 # 2 2
То есть R не резервирует места для этого нулевого объекта. 2 В то же время, глядя
?'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 Еще одно сходство с теорией множеств: пустое множество - это подмножество каждого множества, но мы не резервируем для него места.
источник
Позвольте предположить, что ваш data.frame представляет собой смесь разных типов данных, и не все столбцы нужно изменять.
чтобы изменить только столбцы с 12 по 18 (из всего 21), просто сделайте это
df[, 12:18][df[, 12:18] == 0] <- NA
источник
[]
отличным! Такой очевидный и все еще такой скрытый :)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
источник
Альтернативный способ без
[<-
функции:Образец кадра данных
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
источник
#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
источник
Поскольку кто-то попросил эту версию 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
источник
for (j in names(DT)); set(DT,which(DT[[j]] == 0),j,NA)
. См. Здесь более подробное обсуждение использования data.table для поиска и замены значений.Вы можете заменить
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)
.источник
1:5
с1:ncol(df)
в конце. Я не хотел делать уравнение слишком сложным или трудным для чтения.1:5
на номера столбцов , которые вы хотите изменились, как12:15
, но если вы хотите , чтобы подтвердить , что он будет воздействовать только на числовые столбцы , то просто завернуть вторую строчку функции в , если заявление, как это:if (is.numeric(col)) { col[col == -1 & is.numeric(col)] <- NA }
.Если кто-то прибывает сюда через Google и ищет обратное (например, как заменить все NA в data.frame на 0), ответ будет
df[is.na(df)] <- 0
ИЛИ
Использование dplyr / tidyverse
library(dplyr) mtcars %>% replace(is.na(.), 0)
источник