Эффективная очистка отсутствующего значения в кадре данных в R - PullRequest
0 голосов
/ 04 декабря 2018
require (data.table)
dat1 <- fread('https://archive.ics.uci.edu/ml/machine-learning-databases/primary-tumor/primary-tumor.data',stringsAsFactors=T)

Я хотел бы заменить ? и отсутствующие значения на наиболее частые значения в столбце и сделать их factor (для RandomForest).Я попытался опустить ? из dat1 $ V4:

> dat2=subset(dat1, dat1$V4!='?')
Error in `[.data.table`(x, r, vars, with = FALSE) : 
  i evaluates to a logical vector length 339 but there are 184 rows. Recycling of logical i is no longer allowed as it hides more bugs than is worth the rare convenience. Explicitly use rep(...,length=.N) if you really need to recycle.

И потом, в случае успеха, использовать для make все dataframe столбцы factor:

dat1 <- data.frame(lapply(dat1, as.factor))

Вот заголовок dat1:

> head (dat1)
   V1 V2 V3 V4 V5 V6 V7 V8 V9 V10 V11 V12 V13 V14 V15 V16 V17 V18
1:  1  1  1  ?  3  2  2  1  2   2   2   2   2   2   2   2   2   2
2:  1  1  1  ?  3  2  2  2  2   2   1   2   2   2   1   2   1   2
3:  1  1  2  2  3  1  2  2  2   2   2   2   2   2   2   2   1   2
4:  1  1  2  ?  3  1  2  1  1   2   2   2   2   2   2   2   1   2
5:  1  1  2  ?  3  1  2  1  1   2   2   2   2   2   2   2   1   2
6:  1  1  2  ?  3  1  2  2  2   2   2   1   2   2   1   1   1   2

Вот это str(dat1):

> str (dat1)
Classes ‘data.table’ and 'data.frame':  339 obs. of  18 variables:
 $ V1 : int  1 1 1 1 1 1 1 1 1 1 ...
 $ V2 : int  1 1 1 1 1 1 2 2 2 2 ...
 $ V3 : Factor w/ 3 levels "1","2","?": 1 1 2 2 2 2 1 1 1 1 ...
 $ V4 : Factor w/ 4 levels "1","2","3","?": 4 4 2 4 4 4 1 1 1 1 ...
 $ V5 : Factor w/ 4 levels "1","2","3","?": 3 3 3 3 3 3 1 1 1 2 ...
 $ V6 : int  2 2 1 1 1 1 1 1 2 1 ...
 $ V7 : int  2 2 2 2 2 2 2 2 2 2 ...
 $ V8 : int  1 2 2 1 1 2 2 2 2 2 ...
 $ V9 : int  2 2 2 1 1 2 2 2 2 2 ...
 $ V10: int  2 2 2 2 2 2 2 2 2 2 ...
 $ V11: int  2 1 2 2 2 2 2 2 2 2 ...
 $ V12: int  2 2 2 2 2 1 2 2 2 2 ...
 $ V13: Factor w/ 3 levels "1","2","?": 2 2 2 2 2 2 1 2 2 3 ...
 $ V14: int  2 2 2 2 2 2 1 2 1 1 ...
 $ V15: int  2 1 2 2 2 1 1 2 2 1 ...
 $ V16: Factor w/ 3 levels "1","2","?": 2 2 2 2 2 1 2 2 2 2 ...
 $ V17: int  2 1 1 1 1 1 2 2 2 2 ...
 $ V18: int  2 2 2 2 2 2 2 2 2 2 ...
 - attr(*, ".internal.selfref")=<externalptr>

Ответы [ 2 ]

0 голосов
/ 04 декабря 2018

Хотя это вроде "хакерский", это должно вас туда доставить.Я не видел ни одного NA в вашем data.frame.

library(dplyr)
library(stringr)

dat1 <- read.table('https://archive.ics.uci.edu/ml/machine-learning- 
databases/primary-tumor/primary-tumor.data',stringsAsFactors=T, sep = ",")

dat1 <- sapply(dat1, as.character)
temp <- list()

for (i in 1:ncol(dat1)){
  temp[i] <- data.frame(str_replace(dat1[,i], "[?]",names(sort(table(dat1[,i]), 
decreasing = T))[1]))

}
dat2 <- bind_cols(temp)
colnames(dat2) <- colnames(dat1)
0 голосов
/ 04 декабря 2018

Следующая функция заменяет все значения NA и '?' на наиболее частые значения столбца.Тогда это всего лишь вопрос lapply его передачи в data.frame.

mostFreq <- function(x, na = '?'){
  i <- is.na(x) | x %in% na
  tbl <- table(x[!i])
  x[i] <- names(tbl)[which.max(tbl)]
  if(is.factor(x)) x <- droplevels(x)
  x
}

# Before    
as.list(dat1[1:20, 1:3])
#$V1
# [1] "1" "?" "2" "?" "2" NA  "?" "?" "2" "?" "?" "?" NA  NA 
#[15] NA  NA  "?" "2" "2" "2"
#
#$V2
# [1] "1" "3" "2" "3" "1" "2" "1" "2" "3" "1" "2" "1" "?" NA 
#[15] "?" "3" "1" NA  "?" "1"
#
#$V3
# [1] "?" "1" "?" "3" "1" NA  NA  "3" "1" "1" "1" "2" NA  NA 
#[15] NA  NA  "?" "?" NA  "2"

# After
lapply(dat1[1:20, 1:3], mostFreq)
#$V1
# [1] "1" "2" "2" "2" "2" "2" "2" "2" "2" "2" "2" "2" "2" "2"
#[15] "2" "2" "2" "2" "2" "2"
#
#$V2
# [1] "1" "3" "2" "3" "1" "2" "1" "2" "3" "1" "2" "1" "1" "1"
#[15] "1" "3" "1" "1" "1" "1"
#
#$V3
# [1] "1" "1" "1" "3" "1" "1" "1" "3" "1" "1" "1" "2" "1" "1"
#[15] "1" "1" "1" "1" "1" "2"

и изменения всего фрейма данных.

dat1[] <- lapply(dat1, mostFreq)

И приведение к классу factor:

dat1[] <- lapply(dat1, factor)

Редактировать.

Вышеприведенную функцию можно упростить, если вы начнете читать настройку данных na.strings = '?'.

dat1 <- fread(<URI>, na.strings = '?', <other args>)

Затем используйте функцию ниже, где был исходный mostFreq.

mostFreq2 <- function(x){
  tbl <- table(x, useNA = "no")
  x[is.na(x)] <- names(tbl)[which.max(tbl)]
  x
}

Тестовые данные.

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

set.seed(1234)    # Make the results reproducible
n <- 300
x <- replicate(6, sample(c(NA, '?', 1:2), n, TRUE))
y <- replicate(6, sample(c(NA, '?', 1:3), n, TRUE))
dat1 <- cbind.data.frame(x, y, stringsAsFactors = FALSE)
dat1 <- dat1[, sample(ncol(dat1))]
names(dat1) <- paste0('V', 1:12)
str(dat1)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...