2013-02-20 23 views
5

Sto lavorando a evitare l'eccessivo affollamento delle etichette nel seguente grafico:evitando sovraffollamento delle etichette in r grafici

set.seed(123) 
position <- c(rep (0,5), rnorm (5,1,0.1), rnorm (10, 3,0.1), rnorm (3, 4, 0.2), 5, rep(7,5), rnorm (3, 8,2), rnorm (10,9,0.5), 
       rep (0,5), rnorm (5,1,0.1), rnorm (10, 3,0.1), rnorm (3, 4, 0.2), 5, rep(7,5), rnorm (3, 8,2), rnorm (10,9,0.5)) 
group <- c(rep (1, length (position)/2),rep (2, length (position)/2) ) 
mylab <- paste ("MR", 1:length (group), sep = "") 
barheight <- 0.5 

y.start <- c(group-barheight/2) 
y.end <- c(group+barheight/2) 
mydf <- data.frame (position, group, barheight, y.start, y.end, mylab) 


plot(0,type="n",ylim=c(0,3),xlim=c(0,10),axes=F,ylab="",xlab="") 
#Create two horizontal lines 
require(fields) 
yline(1,lwd=4) 
yline(2,lwd=4) 
#Create text for the lines 
text(10,1.1,"Group 1",cex=0.7) 
text(10,2.1,"Group 2",cex=0.7) 
#Draw vertical bars 
lng = length(position)/2 
lg1 = lng+1 
lg2 = lng*2 
segments(mydf$position[1:lng],mydf$y.start[1:lng],y1=mydf$y.end[1:lng]) 
segments(mydf$position[lg1:lg2],mydf$y.start[lg1:lg2],y1=mydf$y.end[lg1:lg2]) 
text(mydf$position[1:lng],mydf$y.start[1:lng]+0.65, mydf$mylab[1:lng], srt = 90) 
text(mydf$position[lg1:lg2],mydf$y.start[lg1:lg2]+0.65, mydf$mylab[lg1:lg2], srt = 90) 

si possono vedere alcune aree sono affollate con le etichette - quando il valore x è lo stesso o simili. Voglio solo visualizzare solo un'etichetta (quando c'è più etichette nello stesso punto). Ad esempio,

mydf $ posizione [1: 5] sono tutti 0,

ma etichette corrispondenti mydf $ MyLab [1: 5] -

MR1 MR2 MR3 MR4 MR5 

voglio solo mostrare il primo "MR1".

Analogamente i seguenti punti sono troppo vicini (diciamo la differenza di 0,35), dovrebbero essere considerati un singolo cluster e verrà visualizzata la prima etichetta. In questo modo sarei in grado di sbarazzarmi del sovraffollamento delle etichette. Come posso ottenerlo?

enter image description here

+2

Non esiste una soluzione automatica a questi tipi di problemi.In un modo o nell'altro dovrai correggere questo "a mano": o con etichette hard coding per gruppi di linee chiuse, o omettendo tutte le etichette e aggiungendole successivamente con un editor di immagini. – joran

+0

È possibile sottrarre la posizione dai dati di posizione i-1, quindi creare una soglia per creare un cluster. Quindi probabilmente visualizzare un'etichetta per cluster – jon

risposta

10

Se si estrae le etichette e si aggiungono delle linee aggiuntive, è possibile impostare nell'etichetta ogni contrassegno.

clpl <- function(xdata, names, y=1, dy=0.25, add=FALSE){ 
    o = order(xdata) 
    xdata=xdata[o] 
    names=names[o] 
    if(!add)plot(0,type="n",ylim=c(y-1,y+2),xlim=range(xdata),axes=F,ylab="",xlab="") 
    abline(h=1,lwd=4) 
    dy=0.25 
    segments(xdata,y-dy,xdata,y+dy) 
    tpos = seq(min(xdata),max(xdata),len=length(xdata)) 
    text(tpos,y+2*dy,names,srt=90,adj=0) 
    segments(xdata,y+dy,tpos,y+2*dy) 
} 

Quindi, utilizzando i dati:

clpl(mydf$position[lg1:lg2],mydf$mylab[lg1:lg2]) 

dà:

marking lines with callouts

Si potrebbe quindi pensare di cluster di etichettatura sotto la linea principale.

Non ho pensato molto a fare più righe in una trama, ma penso che con un po 'di mucking con il mio codice e il parametro add, dovrebbe essere possibile. Puoi anche usare il colore per mostrare i cluster. Sono abbastanza sicuro che queste tecniche siano presenti in alcuni pacchetti di clustering per R ...

Ovviamente con molti marker anche questo sta per essere immerso, ma con un sacco di cluster la stessa cosa sta per accadere. Forse finisci per etichettare i cluster con questa tecnica?

+0

+1: opzione molto elegante! – Simon

+0

+1 per bella opzione – SHRram

2

In generale, sono d'accordo con @Joran che l'etichettatura cluster non può essere automatizzato, ma ti ho detto che etichettare un gruppo di linee con la prima etichetta del cluster sarebbe OK, quindi è possibile automatizzare parte del processo.

Mettere il seguente codice dopo la linea lg2 = lng*2 dà il risultato mostrato nell'immagine qui sotto:

clust <- cutree(hclust(dist(mydf$position[1:lng])),h=0.75) 
u <- rep(T,length(unique(clust))) 
clust.labels <- sapply(c(1:lng),function (i) 
    { 
    if (u[clust[i]]) 
     { 
     u[clust[i]] <<- F 
     as.character(mydf$mylab)[i] 
     } 
    else 
     { 
     "" 
     } 
    }) 

segments(mydf$position[1:lng],mydf$y.start[1:lng],y1=mydf$y.end[1:lng]) 
segments(mydf$position[lg1:lg2],mydf$y.start[lg1:lg2],y1=mydf$y.end[lg1:lg2]) 
text(mydf$position[1:lng],mydf$y.start[1:lng]+0.65, clust.labels, srt = 90) 
text(mydf$position[lg1:lg2],mydf$y.start[lg1:lg2]+0.65, mydf$mylab[lg1:lg2], srt = 90) 

Labelled Clusters

(ho etichettati solo i grappoli sulla linea inferiore - lo stesso principio potrebbe essere applicato anche alla linea superiore). Il parametro h di cutree() potrebbe dover essere regolato caso per caso per fornire la risoluzione delle etichette desiderate, ma questo approccio è almeno più semplice dell'etichettatura di ogni cluster a mano.

Problemi correlati