Ответ 1
Вы можете сделать:
x[, 1:2][is.na(x[, 1:2])] <- 0
или лучше (IMHO), используйте имена переменных:
x[c("a", "b")][is.na(x[c("a", "b")])] <- 0
В обоих случаях 1:2
или c("a", "b")
можно заменить заранее заданным вектором.
Есть много сообщений о замене значений NA. Я знаю, что можно заменить NA в следующей таблице/фрейме следующим образом:
x[is.na(x)]<-0
Но что, если я хочу ограничить его только определенными столбцами? Позвольте мне показать вам пример.
Сначала начнем с набора данных.
set.seed(1234)
x <- data.frame(a=sample(c(1,2,NA), 10, replace=T),
b=sample(c(1,2,NA), 10, replace=T),
c=sample(c(1:5,NA), 10, replace=T))
Что дает:
a b c
1 1 NA 2
2 2 2 2
3 2 1 1
4 2 NA 1
5 NA 1 2
6 2 NA 5
7 1 1 4
8 1 1 NA
9 2 1 5
10 2 1 1
Хорошо, поэтому я хочу ограничить замену столбцами "a" и "b". Моя попытка:
x[is.na(x), 1:2]<-0
и
x[is.na(x[1:2])]<-0
Что не работает.
Моя попытка data.table, где y<-data.table(x)
, очевидно, никогда не будет работать:
y[is.na(y[,list(a,b)]), ]
Я хочу передать столбцы внутри аргумента is.na, но это явно не сработает.
Я хотел бы сделать это в data.frame и data.table. Моя конечная цель состоит в том, чтобы перекодировать 1: 2 в 0: 1 в 'a' и 'b', сохраняя 'c' так, как это есть, поскольку это не логическая переменная. У меня есть куча столбцов, поэтому я не хочу делать это один за другим. И я просто хотел бы знать, как это сделать.
Есть ли у вас какие-либо предложения?
Вы можете сделать:
x[, 1:2][is.na(x[, 1:2])] <- 0
или лучше (IMHO), используйте имена переменных:
x[c("a", "b")][is.na(x[c("a", "b")])] <- 0
В обоих случаях 1:2
или c("a", "b")
можно заменить заранее заданным вектором.
Это будет работать для вашей версии data.table
:
for (col in c("a", "b")) y[is.na(get(col)), (col) := 0]
В качестве альтернативы, как указывает Дэвид Аренбург, вы можете использовать set
(боковое преимущество - вы можете использовать его либо на data.frame
, либо data.table
):
for (col in 1:2) set(x, which(is.na(x[[col]])), col, 0)
Теперь это тривиально в tidyr с replace_na(). Функция, как представляется, работает для data.tables, а также data.frames:
tidyr::replace_na(x, list(a=0, b=0))
Основываясь на ответе @Robert McDonald tidyr::replace_na()
, вот несколько опций dplyr
для управления тем, какие столбцы заменяются NA
:
library(tidyverse)
# by column type:
x %>%
mutate_if(is.numeric, ~replace_na(., 0))
# select columns defined in vars(col1, col2, ...):
x %>%
mutate_at(vars(a, b, c), ~replace_na(., 0))
# all columns:
x %>%
mutate_all(~replace_na(., 0))
Не уверен, что это более красноречиво, но эта функция также найдет и позволит заменить NA (или любое значение, которое вам нравится) в выбранных столбцах таблицы данных.
update.mat <- function(dt, cols, criteria) {
require(data.table)
x <- as.data.frame(which(criteria==TRUE, arr.ind = TRUE))
y <- as.matrix(subset(x, x$col %in% which((names(dt) %in% cols), arr.ind = TRUE)))
y
}
Чтобы применить его:
y[update.mat(y, c("a", "b"), is.na(y))] <- 0
Функция создает матрицу из выбранных столбцов и строк (координаты ячеек), которые соответствуют входным критериям (в этом случае is.na == TRUE).
Для конкретного столбца существует альтернатива с sapply
DF <- data.frame(A = letters[1:5],
B = letters[6:10],
C = c(2, 5, NA, 8, NA))
DF_NEW <- sapply(seq(1, nrow(DF)),
function(i) ifelse(is.na(DF[i,3]) ==
TRUE,
0,
DF[i,3]))
DF[,3] <- DF_NEW
DF
We can solve it in data.table way with tidyr::repalce_na function and lapply
library(data.table)
library(tidyr)
setDT(df)
df[,c("a","b","c"):=lapply(.SD,function(x) replace_na(x,0)),.SDcols=c("a","b","c")]
In this way,we can also solve paste cloumns with NA string.First, we replace_na(x,""),then we can use stringr::str_c to combine columns!
это очень удобно с {data.table} и {stringr}
library(data.table)
library(stringr)
x[, lapply(.SD, function(xx) {str_replace_na(xx, 0)})]
FYI
это отлично работает для меня
DataTable DT = new DataTable();
DT = DT.AsEnumerable().Select(R =>
{
R["Campo1"] = valor;
return (R);
}).ToArray().CopyToDataTable();