Подтвердить что ты не робот

Удаление постоянных столбцов в R

Я использовал функцию prcomp, когда я получил эту ошибку

Error in prcomp.default(x, ...) : 
cannot rescale a constant/zero column to unit variance

Я знаю, что могу вручную сканировать свои данные, но есть ли какая-либо функция или команда в R, которые могут помочь мне удалить эти постоянные переменные? Я знаю, что это очень простая задача, но я никогда не сталкивался с какой-либо функцией, которая делает это.

Спасибо,

4b9b3361

Ответ 1

Проблема заключается в том, что ваша дисперсия столбца равна нулю. Вы можете проверить, какой столбец кадра данных является постоянным таким образом, например:

df <- data.frame(x=1:5, y=rep(1,5))
df
#   x y
# 1 1 1
# 2 2 1
# 3 3 1
# 4 4 1
# 5 5 1

# Supply names of columns that have 0 variance
names(df[, sapply(df, function(v) var(v, na.rm=TRUE)==0)])
# [1] "y" 

Итак, если вы хотите исключить эти столбцы, вы можете использовать:

df[,sapply(df, function(v) var(v, na.rm=TRUE)!=0)]

EDIT: На самом деле проще использовать apply. Что-то вроде этого:

df[,apply(df, 2, var, na.rm=TRUE) != 0]

Ответ 2

Я предполагаю, что этот Q & A является популярным результатом поиска Google, но ответ немного медленный для большой матрицы, плюс у меня нет достаточной репутации, чтобы прокомментировать первый ответ. Поэтому я отправляю новый ответ на вопрос.

Для каждого столбца большой матрицы достаточно проверить, равен ли максимум минимуму.

df[,!apply(df, MARGIN = 2, function(x) max(x, na.rm = TRUE) == min(x, na.rm = TRUE))]

Это тест. Более 90% времени сокращается по сравнению с первым ответом. Это также быстрее, чем ответ со второго комментария к вопросу.

ncol = 1000000
nrow = 10
df <- matrix(sample(1:(ncol*nrow),ncol*nrow,replace = FALSE), ncol = ncol)
df[,sample(1:ncol,70,replace = FALSE)] <- rep(1,times = nrow) # df is a large matrix

time1 <- system.time(df1 <- df[,apply(df, 2, var, na.rm=TRUE) != 0]) # the first method
time2 <- system.time(df2 <- df[,!apply(df, MARGIN = 2, function(x) max(x, na.rm = TRUE) == min(x, na.rm = TRUE))]) # my method
time3 <- system.time(df3 <- df[,apply(df, 2, function(col) { length(unique(col)) > 1 })]) # Keith method

time1
#   user  system elapsed 
# 22.267   0.194  22.626 
time2
#   user  system elapsed 
#  2.073   0.077   2.155 
time3
#   user  system elapsed 
#  6.702   0.060   6.790
all.equal(df1, df2)
# [1] TRUE
all.equal(df3, df2)
# [1] TRUE

Ответ 3

Так как этот Q & A является популярным результатом поиска Google, но ответ немного медленный для большой матрицы, а версия @raymkchow медленна с NAs, я предлагаю новую версию с использованием экспоненциального поиска и data.table power.

Это функция, которую я реализовал в пакете dataPreparation.

Сначала создайте примерную таблицу данных с большим количеством строк, чем столбцы (как правило, это так) и 10% от NA

ncol = 1000
nrow = 100000
df <- matrix(sample(1:(ncol*nrow),ncol*nrow,replace = FALSE), ncol = ncol)
df <- apply (df, 2, function(x) {x[sample( c(1:nrow), floor(nrow/10))] <- NA; x} ) # Add 10% of NAs
df[,sample(1:ncol,70,replace = FALSE)] <- rep(1,times = nrow) # df is a large matrix
df <- as.data.table(df)

Затем сравните все подходы:

time1 <- system.time(df1 <- df[,apply(df, 2, var, na.rm=TRUE) != 0, with = F]) # the first method
time2 <- system.time(df2 <- df[,!apply(df, MARGIN = 2, function(x) max(x, na.rm = TRUE) == min(x, na.rm = TRUE)), with = F]) # raymkchow
time3 <- system.time(df3 <- df[,apply(df, 2, function(col) { length(unique(col)) > 1 }), with = F]) # Keith method
time4 <- system.time(df4 <- df[,-whichAreConstant(df, verbose=FALSE)]) # My method

Результаты следующие:

time1 # Variance approch
#   user  system elapsed 
#   2.55    1.45    4.07
time2 # Min = max approach
#   user  system elapsed 
#  2.72      1.5    4.22
time3 # length(unique()) approach
#   user  system elapsed 
#    6.7    2.75    9.53
time4 # Exponential search approach
#   user  system elapsed 
#   0.39    0.07    0.45
all.equal(df1, df2)
# [1] TRUE
all.equal(df3, df2)
# [1] TRUE
all.equal(df4, df2)
# [1] TRUE

dataPreparation:whichAreConstant в 10 раз быстрее, чем другие подходы.

Плюс к тому, что больше строк у вас больше, тем лучше.