usando ggpairs com dados de contenção de NA

9

ggpairs no pacote GGally parece bastante útil, mas parece falhar quando há NA presente em qualquer lugar no conjunto de dados:

#require(GGally)
data(tips, package="reshape")
pm <- ggpairs(tips[,1:3]) #works just fine

#introduce NA
tips[1,1] <- NA
ggpairs(tips[,1:3])
> Error in if (lims[1] > lims[2]) { : missing value where TRUE/FALSE needed

Não vejo nenhuma documentação para lidar com NA valores, e soluções como ggpairs(tips[,1:3], na.rm=TRUE) (sem surpresas) não alteram a mensagem de erro.

Eu tenho um conjunto de dados no qual talvez 10% dos valores sejam NA , aleatoriamente espalhados por todo o conjunto de dados. Portanto, na.omit(myDataSet) removerá muitos dos dados. Existe alguma maneira de contornar isso?

    
por Drew Steen 26.10.2012 в 22:26
fonte

3 respostas

3

Algumas funções de GGally como ggparcoord() suportam o tratamento de NAs pelo parâmetro missing=[exclude,mean,median,min10,random] . No entanto, este não é o caso de ggpairs() , infelizmente.

O que você pode fazer é substituir NAs por uma boa estimativa de seus dados que você esperava que o ggpair() faça automaticamente para você. Existem boas soluções, como substituí-las por row significa , zeros , mediano ou mesmo ponto mais próximo (Observe 4 hyperlinks nas palavras da sentença recente!).

    
por Ali 27.10.2012 / 03:02
fonte
1

Eu vou dar uma olhada nisso com minha própria solução horrível, porque acho que isso precisa de estímulo. Eu concordo com OP que preencher dados baseados em suposições estatísticas ou um hack escolhido é uma péssima idéia para análise exploratória, e eu acho que é garantido falhar assim que você esquecer como funciona (cerca de cinco dias para mim) e precisar ajustar para outra coisa.

Aviso de isenção

Esta é uma maneira terrível de fazer as coisas, e eu odeio isso. É útil para quando você tem uma fonte sistemática de NAs provenientes de algo como amostragem esparsa de um conjunto de dados de alta dimensão, que talvez o OP tenha.

Exemplo

Digamos que você tenha um pequeno subconjunto de um conjunto de dados muito maior, tornando algumas de suas colunas esparsamente representadas:

|  Sample (0:350)|  Channel(1:118)|  Trial(1:10)|     Voltage|Class  (1:2)|  Subject (1:3)|
|---------------:|---------------:|------------:|-----------:|:-----------|--------------:|
|               1|               1|            1|  0.17142245|1           |              1|
|               2|               2|            2|  0.27733185|2           |              2|
|               3|               1|            3|  0.33203066|1           |              3|
|               4|               2|            1|  0.09483775|2           |              1|
|               5|               1|            2|  0.79609409|1           |              2|
|               6|               2|            3|  0.85227987|2           |              3|
|               7|               1|            1|  0.52804960|1           |              1|
|               8|               2|            2|  0.50156096|2           |              2|
|               9|               1|            3|  0.30680522|1           |              3|
|              10|               2|            1|  0.11250801|2           |              1|

require(data.table) # needs the latest rForge version of data.table for dcast
sample.table <- data.table(Sample = seq_len(10), Channel = rep(1:2,length.out=10),
                           Trial = rep(1:3, length.out=10), Voltage = runif(10), 
                           Class = as.factor(rep(1:2,length.out=10)),
                           Subject = rep(1:3, length.out=10))

O exemplo é falso, mas finja que as colunas são uniformemente amostradas de seus subconjuntos maiores.

Digamos que você queira transmitir os dados para o formato amplo em todos os canais para plotar com ggpairs . Agora, um canônico dcast de volta para o formato amplo não funcionará, com uma coluna id ou porque os intervalos de coluna são esparsamente (e nunca completamente) representados:

wide.table <- dcast.data.table(sample.table, Sample ~ Channel,
                                   value.var="Voltage",
                                   drop=TRUE)

> wide.table
        Sample         1          2
     1:      1 0.1714224         NA
     2:      2        NA 0.27733185
     3:      3 0.3320307         NA
     4:      4        NA 0.09483775
     5:      5 0.7960941         NA
     6:      6        NA 0.85227987
     7:      7 0.5280496         NA
     8:      8        NA 0.50156096
     9:      9 0.3068052         NA
    10:     10        NA 0.11250801

É óbvio, neste caso, que coluna id funcionaria porque é um exemplo de brinquedo ( sample.table[,index:=seq_len(nrow(sample.table)/2)] ), mas é basicamente impossível no caso de uma pequena amostra uniforme de um grande volume de dados. id valores que serão inseridos em todos os buracos em seus dados quando aplicados ao argumento da fórmula. Este kludge funcionará:

setkey(sample.table,Class)

Precisamos disso no final para garantir que a ordem seja corrigida.

chan.split <- split(sample.table,sample.table$Channel)

Isso fornece uma lista de data.frames para cada canal exclusivo.

cut.fringes <- min(sapply(chan.split,function(x) nrow(x)))
chan.dt <- cbind(lapply(chan.split, function(x){
  x[1:cut.fringes,]$Voltage}))

Tem que haver uma maneira melhor de garantir que cada data.frame tenha um número igual de linhas, mas, para o meu aplicativo, posso garantir que elas são apenas algumas linhas diferentes, então eu apenas apago as linhas em excesso. / p>

chan.dt <- as.data.table(matrix(unlist(chan.dt),
                 ncol = length(unique(sample.table$Channel)), 
                 byrow=TRUE))

Isso levará você de volta a um grande data.table, com canais como colunas.

chan.dt[,Class:=
         as.factor(rep(0:1,each=sampling.factor/2*nrow(original.table)/ncol(chan.dt))[1:cut.fringes])]

Por fim, reconecto minha variável categórica novamente. As tabelas devem ser classificadas por categoria, portanto, isso corresponderá. Isso pressupõe que você tenha a tabela original com todos os dados; existem outras maneiras de fazer isso.

ggpairs(data=chan.dt,
        columns=1:length(unique(sample.table$Channel)), colour="Class",axisLabels="show")

Agora é plausível com o acima.

    
por bright-star 20.01.2014 / 11:42
fonte
1

Tanto quanto eu posso dizer, não há maneira de contornar isso com ggpairs (). Além disso, você está absolutamente correto em não preencher com dados "falsos". Se for apropriado sugerir aqui, eu recomendaria usar um método de plotagem diferente. Por exemplo

 cor.data<- cor(data,use="pairwise.complete.obs") #data correlations ignoring pair-wise NA's
 chart.Correlation(cor.data) #library(PerformanceAnalytics)

ou usando o código aqui link

    
por user3708129 01.07.2014 / 20:03
fonte