2016-01-03 11 views
11

Sto cercando di creare (in plotly) uno scatterplot che distingua i punti della stessa serie da due (o tre) estetiche - colore, forma, dimensione. In definitiva, l'obiettivo è quello di poter attivare/disattivare i gruppi di punti tramite la legenda, utilizzando una delle tre estetiche. Questo funziona bene per un'estetica.Come applicare contemporaneamente colore/forma/dimensione in un grafico a dispersione usando trama?

[Aggiunto il 2016-06-20] Per espandere il comportamento interattivo desiderato: L'idea è, una volta mostrata la figura, di essere in grado di alternare gruppi di punti facendo clic su una qualsiasi delle legende. Ad esempio (nei dati di esempio qui sotto), se dovessi fare clic su nella legenda, nascondere/mostrare i punti # 4, 5 e 10 di tutte le serie. Se c'è un clic su A, quindi alternare i punti n. 1, 2 e 8. Come caso di utilizzo nella vita reale - si pensi ai prezzi delle obbligazioni, con scadenza sull'asse orizzontale e prezzo sulla verticale. Le obbligazioni sono caratterizzate dal paese di origine, dalla solvibilità e dalla dimensione del problema. Quindi, se faccio clic su, ad esempio, sulla valutazione "A" del credito, vorrei che tutti i problemi con classificazione A, indipendentemente dalla dimensione e dal paese di origine, fossero nascosti. Attualmente sono solo nascosti dalla traccia relativa alla valutazione. I punti nelle tracce che riflettono gli altri attributi (dimensione & paese) rimangono visualizzati. Data la risposta dettagliata qui sotto, sono propenso a postare questa come richiesta di funzionalità sul sito di plotly.

ho inquadrato la questione per plotly, ma se questo comportamento può essere ottenuto in un altro pacchetto/libreria da R con livelli di dolore relativamente bassi (cioè senza JavaScript personalizzato o simili), accetterò che come una risposta troppo . [modifica fine]

La parte statica è fatto facilmente in ggplot2 ma non riesco a ricreare in plotly (per l'interattività), anche utilizzando ggplotly(). Non sono sicuro che sia possibile, ma ho pensato di chiedere. Esempio di dati & codice qui sotto.

(possibilmente correlate al Using 2+ legends from R to plotly/plot.ly)

generare alcuni dati fittizi:

library(data.table) 
library(plotly) 
library(ggplot2) 


DT <- data.table(
    x = c(1:10), y = 1:10/2, 
    gr1 = c("A", "A", "B", "C", "D", "D", "B", "A", "E", "E"), 
    gr2 = c("x", "x", "x", "y", "y", "z", "z", "x", "x", "y"), 
    gr3 = c(1,2,2,1,3,4,1,2,2,1) 
) 

La versione ggplot() assomiglia a questo, ed è quello che mi piacerebbe entrare in plotly:

p <- ggplot(data = DT) + geom_point(aes(x = x, y = y, color = gr1, shape = gr2, size = gr3)) 
p 

Nella legenda ci sono tre gruppi di criteri e i punti hanno colori, forme e dimensioni variabili. ggplot version

Calling ggplotly(p) genera una serie di avvertimenti:

Warning messages: 
1: In if (s == Inf) { : 
    the condition has length > 1 and only the first element will be used 
2: In if (s == Inf) { : 
    the condition has length > 1 and only the first element will be used 
3: In if (s == Inf) { : 
    the condition has length > 1 and only the first element will be used 
4: In if (s == Inf) { : 
    the condition has length > 1 and only the first element will be used 
5: In if (s == Inf) { : 
    the condition has length > 1 and only the first element will be used 
6: In if (s == Inf) { : 
    the condition has length > 1 and only the first element will be used 
7: In if (s == Inf) { : 
    the condition has length > 1 and only the first element will be used 
8: In if (s == Inf) { : 
    the condition has length > 1 and only the first element will be used 

e produce questa cifra:

ggplotly version

Cercando di utilizzare plot_ly(), ottengo il seguente:

plot_ly(data = DT, x = x, y = y, color = gr1, symbol = gr2, type = "scatter", mode = "markers", marker = list(size = 10 * gr3)) # size is multiplied by 10, in plotly it is in pixels 

plot_ly version

Il problema è più ovvio nel mezzo della figura: al posto di una croce colorata, ci sono diverse forme con colori diversi sovrapposti l'una sull'altra. Poiché si tratta di un singolo punto, mi aspetto una singola forma colorata, come in ggplot. Nella trama, gli argomenti "colore", "simbolo" e "dimensione" creano una nuova traccia?

Sono ancora abbastanza nuovo a plotly, quindi potrei mancare qualcosa di ovvio.

Quanto sopra viene eseguito utilizzando R 3.2.2 in Windows, con plotly_2.0.16 e ggplot2_2.0.0.

risposta

3

Sfortunatamente, questo comportamento non viene generato automaticamente. Ma può essere fatto semplicemente specificando il colore, la forma e la dimensione di ogni singolo punto, usando gli argomenti colors =, size = e symbols =. Ciò consente di controllare il modo in cui i punti vengono tracciati, ma non ottiene la legenda desiderata. Quindi utilizziamo showlegend = FALSE nel grafico principale e costruiamo la legenda aggiungendo altre tre tracce (invisibili) che sono lì solo per generare gli elementi della legenda.

Nota che c'è un altro trucco che dobbiamo applicare qui. Per ottenere una legenda che mostri colori o taglie, puoi utilizzare l'argomento visible = "legendonly" che crea una voce della legenda senza tracciare punti extra sul grafico. MA questo non funziona con le forme. La combinazione di visible = "legendonly" con symbols = sembra avere un bug che inserisce gli elementi errati nella legenda. Quindi, per creare le voci della legenda per le forme, puoi tracciarle in una posizione lontana nella stratosfera in cui non saranno mai visibili (qui ho usato x = y = 1e6) e ho impostato i limiti dell'asse xey per tenerli fuori di vista.

DT <- data.table(
    x = c(1:10), y = 1:10/2, 
    gr1 = as.factor(c("A", "A", "B", "C", "D", "D", "B", "A", "E", "E")), 
    gr2 = as.factor(c("x", "x", "x", "y", "y", "z", "z", "x", "x", "y")), 
    gr3 = c(1,2,2,1,3,4,1,2,2,1) 
) 
shapes <- c("circle", "square", "diamond","cross", "x","square-open","circle-open","diamond-open") 
DT$shapes <- shapes[DT$gr1] 
DT$col <- rainbow(3)[DT$gr2] 
DT$size <- DT$gr3*10 

plot_ly() %>% 
    add_trace(data = DT, x = x, y = y, type = "scatter", mode = "markers", 
      color=gr2, colors=col, 
      marker = list(size = size, symbol=shapes), showlegend=F) %>% 
    add_trace(data = DT, x = x, y = y, type = "scatter",mode = "markers", 
      color= factor(gr2), colors=col, 
      visible="legendonly", showlegend=T, legendgroup="color", 
      marker = list(size = 14)) %>% 
    add_trace(data = DT, x = x, y = y, type = "scatter",mode = "markers", 
      color=factor(gr3), colors="#000000", 
      marker = list(size = size), 
      visible="legendonly", showlegend=T, legendgroup="size") %>% 
    add_trace(data = DT, x = 1e6, y = 1e6, type = "scatter", mode = "markers", 
      color=factor(gr1), colors="#000000", 
      marker = list(size=14, symbol=shapes), 
      showlegend=T, legendgroup="shape") %>% 
    layout(legend=list(traceorder="grouped+reversed", tracegroupgap =30), 
     xaxis=list(range=c(0,12)), 
     yaxis=list(range=c(0,6))) 

enter image description here

+0

Grazie per la risposta interessante, il "lontano nella stratosfera" è un bel tocco :) E sembra per risolvere la parte visiva in larga misura (cliccando sulla leggenda distrugge la effetto, poiché traccia un'altra forma sulle precedenti). La domanda di base, tuttavia, era l'interattività (nella prima frase) - che non sembra funzionare. L'idea è, se faccio clic su "C", "y" o "1" nelle legende per far sparire il punto 4 (x = 4, y = 2.0). Dovrebbe nascondere il rispettivo punto di tutte e tre le serie, che non sono sicuro sia disponibile in "trama". – Peter

+1

Se non si desidera fare clic sulla legenda per sovrascrivere i punti (questo attiva effettivamente lo stato di visibilità), quindi utilizzare semplicemente il metodo stratosfera per ciascuna delle voci della legenda. Se vuoi un comportamento più complesso di questo, allora buona fortuna ... dubita che tu possa farlo in modo molto dettagliato. – dww

+0

Sì, ho pensato di volere troppo :) Sono aperto a suggerimenti per altri pacchetti/librerie di quanto si possa fare, se esistono. Grazie ancora - anche se non posso accettare la risposta a questa domanda immediata, ho imparato un trucco utile. – Peter