2017-02-22 5 views
6

Ich habe einen bivariaten Datensatz mit 100 Beobachtungen. Ich benutzte Sechseck Binning und endete mit 26 Sechseck Bins. Um die Reihen der 100 Beobachtungen zu speichern, die in jeder der 26 Sechseck-Bins sind, ich die base::attr Funktion in R. Im folgenden Code verwendet wird, geschieht dies auf:R Objektattribute in JavaScript abrufen

attr(hexdf, "cID") <- [email protected] 

I zu schaffen versuche ein interaktives R Plotly Objekt des Sechseck-Binnings, so dass, wenn ein Benutzer auf ein gegebenes Sechseck-Fach klicken würde, sie die Reihen der 100 Beobachtungen erhalten würden, die in diesem Fach gruppiert waren. Ich habe einen Teil dieses Ziels abgeschlossen. Mein MWE unten:

library(plotly) 
library(data.table) 
library(GGally) 
library(hexbin) 
library(htmlwidgets) 

set.seed(1) 
bindata <- data.frame(ID = paste0("ID",1:100), A=rnorm(100), B=rnorm(100)) 
bindata$ID <- as.character(bindata$ID) 

x = bindata[,c("A")] 
y = bindata[,c("B")] 
h <- hexbin(x=x, y=y, xbins=5, shape=1, IDs=TRUE) 
hexdf <- data.frame (hcell2xy (h), hexID = [email protected], counts = [email protected]) 
attr(hexdf, "cID") <- [email protected] 
pS <- ggplot(hexdf, aes(x=x, y=y, fill = counts, hexID=hexID)) + geom_hex(stat="identity") 

ggPS <- ggplotly(pS) 

myLength <- length(ggPS[["x"]][["data"]]) 
for (i in 1:myLength){ 
    item =ggPS[["x"]][["data"]][[i]]$text[1] 
    if (!is.null(item)) 
    if (!startsWith(item, "co")){ 
     ggPS[["x"]][["data"]][[i]]$hoverinfo <- "none" 
    } 
} 

ggPS %>% onRender(" 
      function(el, x, data) { 
      //console.log(el) 
      //console.log(x) 
      //console.log(data) 

      myGraph = document.getElementById(el.id); 
      el.on('plotly_click', function(e) { 

      cN = e.points[0].curveNumber 
      split1 = (x.data[cN].text).split(' ') 
      hexID = (x.data[cN].text).split(' ')[2] 
      counts = split1[1].split('<')[0] 
      console.log(hexID) 
      console.log(counts) 

      })} 
      ", data = pS$data) 

Wenn ich diesen Code ausführen und öffnen Sie sie im Web-Browser, ich erhalten eine interaktive Handlung wie unten (grüne Box ist nicht in Handlung, es ist zu Erläuterungszwecken überlagert ist):

enter image description here

Wenn ich innerhalb der grünen Box auf dem Sechseck klicken, werden die richtige hexID von 40 und counts von 3 auf der Konsole ausgegeben. An dieser Stelle möchte ich die 3 Zeilen des ursprünglichen Datenrahmens erhalten, die in dieses Sechseckfach gelegt wurden.

Ich weiß, wie man dies in R außerhalb der onRender() Funktion des htmlwidgets Pakets mit Hilfe der base::attr Funktion. Zum Beispiel kann ich folgendes tun:

hexID=40 
obsns <- which(attr(pS$data, "cID")==hexID) 
dat <- bindata[obsns,] 

und die folgenden korrekten 3 Datenpunkte erhalten, die in diese Behälter gesetzt wurde ich auf geklickt habe:

 ID   A  B 
47 ID47 0.3645820 2.087167 
66 ID66 0.1887923 2.206102 
71 ID71 0.4755095 2.307978 

ich mit viel größeren Datensatz arbeitete als in dieser MWE. Aus diesem Grund war es meine Absicht, die base:attr Funktion zu verwenden, um zu verhindern, dass immer größere Datenrahmen herumfließen. Ich bin jedoch nicht sicher, wie die Funktionalität der base::attr-Funktion übersetzt wird, damit ich auf die entsprechenden Datenpunktzeilen zugreifen kann, die in einem angeklickten Sechseckfach in dem JavaScript-Code onRender() auftreten. Ich habe das Objekt pS$data in den JavaScript-Code onRender() eingefügt, bin aber immer noch fest.

Jeder Rat würde herzlichst geschätzt werden!

Antwort

2

Sie könnten eine Spalte hinzufügen, die für jede Zeile die ID des hexbin muss es in Ihrem BinData gehört:

bindata$hex <- [email protected] 

Sie können dann geben sie an die onRender Funktion und Filterreihen, wenn die Benutzer auf klickt ein Sechseck:

ggPS %>% onRender(" 
        function(el, x, data) { 
        myGraph = document.getElementById(el.id); 
        el.on('plotly_click', function(e) { 

        cN = e.points[0].curveNumber 
        split1 = (x.data[cN].text).split(' ') 
        hexID = (x.data[cN].text).split(' ')[2] 
        counts = split1[1].split('<')[0] 

        var selected_rows = []; 

        data.forEach(function(row){ 
        if(row.hex==hexID) selected_rows.push(row); 
        }); 
        console.log(selected_rows); 

        })} 
        ", data = bindata) 
+0

Vielen Dank für die Hilfe! Mir ist klar, dass mir die Voraussicht fehlte und mein MWE zu stark vereinfacht wurde, so dass es eine Lösung gibt (wie du gezeigt hast), die nicht benötigt wird, um base :: attr() zu verwenden. Die Lösung kann immer noch hilfreich für mich und andere sein. Ich habe gerade eine bessere MWE geschrieben, die hoffentlich deutlicher zeigt, warum ich mich immer noch mit der Basis festsetze: attr() und warum ich nicht glaube, dass die Lösung hier für diesen Fall funktionieren wird. Ich postete das in einer Version von Teil 2 (http://stackoverflow.com/questions/42460061/retrieving-r-object-attributes-in-javascript-part-2). Vielen Dank. – luckButtered

+1

Ich habe die gleiche Strategie für Teil 2 funktioniert, ich habe eine Lösung gepostet, die hoffentlich auf Ihr vollständiges Beispiel funktioniert. – NicE

Verwandte Themen