Удалить постоянные столбцы с или без NA
Я пытаюсь заставить много моделей lm
работать в функции, и мне нужно автоматически отбрасывать постоянные столбцы из моей таблицы данных. Таким образом, я хочу сохранить только столбцы с двумя или более уникальными значениями, исключая NA
из count.
Я попробовал несколько методов, найденных в SO, но я все еще не могу удалить столбцы, которые имеют два значения: константу и NA.
Мой воспроизводимый код:
library(data.table)
df <- data.table(x=c(1,2,3,NA,5), y=c(1,1,NA,NA,NA),z=c(NA,NA,NA,NA,NA),
d=c(2,2,2,2,2))
> df
x y z d
1: 1 1 NA 2
2: 2 1 NA 2
3: 3 NA NA 2
4: NA NA NA 2
5: 5 NA NA 2
Мое намерение состоит в том, чтобы удалить столбцы y, z и d, поскольку они являются константами, включая y, которые имеют только одно уникальное значение, когда NA
опущены.
Я пробовал это:
same <- sapply(df, function(.col){ all(is.na(.col)) || all(.col[1L] == .col)})
df1 <- df[ , !same, with = FALSE]
> df1
x y
1: 1 1
2: 2 1
3: 3 NA
4: NA NA
5: 5 NA
Как видно, 'y' все еще существует...
Любая помощь?
Ответы
Ответ 1
Поскольку у вас есть data.table
, вы можете использовать uniqueN
и его аргумент na.rm
:
df[ , lapply(.SD, function(v) if(uniqueN(v, na.rm = TRUE) > 1) v)]
# x
# 1: 1
# 2: 2
# 3: 3
# 4: NA
# 5: 5
Альтернативой A base
может быть Filter(function(x) length(unique(x[!is.na(x)])) > 1, df)
Ответ 2
В базе r
существует простое решение с функцией Filter
. Это поможет.
library(data.table)
df <- data.table(x=c(1,2,3,NA,5), y=c(1,1,NA,NA,NA),z=c(NA,NA,NA,NA,NA),
d=c(2,2,2,2,2))
# Select only columns for which SD is not 0
> Filter(function(x) sd(x, na.rm = TRUE) != 0, df)
x
1: 1
2: 2
3: 3
4: NA
5: 5
Примечание. Не забудьте использовать na.rm = TRUE
.
Ответ 3
Вот вариант:
df[,which(df[,
unlist(
sapply(.SD,function(x) length(unique(x[!is.na(x)])) >1))]),
with=FALSE]
x
1: 1
2: 2
3: 3
4: NA
5: 5
Для каждого столбца таблицы данных мы подсчитываем количество уникальных значений, отличных от NA. Мы сохраняем только столбец с несколькими значениями.
Ответ 4
Проверьте, равна ли дисперсия нулю:
df[, sapply(df, var, na.rm = TRUE) != 0, with = FALSE]
# x
# 1: 1
# 2: 2
# 3: 3
# 4: NA
# 5: 5
Ответ 5
Просто измените
all(is.na(.col)) || all(.col[1L] == .col)
to
all(is.na(.col) | .col[1L] == .col)
Конечный код:
same <- sapply( df, function(.col){ all( is.na(.col) | .col[1L] == .col ) } )
df1 <- df[,!same, with=F]
Результат:
x
1: 1
2: 2
3: 3
4: NA
5: 5
Ответ 6
Если вы действительно имеете в виду DROPing этих столбцов, вот решение:
library(data.table)
dt <- data.table(x=c(1,2,3,NA,5),
y=c(1,1,NA,NA,NA),
z=c(NA,NA,NA,NA,NA),
d=c(2,2,2,2,2))
for (col in names(copy(dt))){
v = var(dt[[col]], na.rm = TRUE)
if (v == 0 | is.na(v)) dt[, (col) := NULL]
}