2017-02-22 12 views
6

Mam dwuwymiarowy zbiór danych zawierający 100 obserwacji. Użyłem sześciokąta binningowego i skończyłem z 26 sześciokątnymi pojemnikami. W celu zaoszczędzenia rzędy 100 uwag, które są w każdym z pojemników sześciokąt 26, użyłem funkcji base::attr w R. W poniższym kodzie, to odbywa się pod adresem:Pobieranie atrybutów obiektów R w JavaScript

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

Próbuję utworzyć interaktywny obiekt R Plotly binningu sześciokątnego tak, że jeśli użytkownik kliknie na dany pojemnik z sześciokątem, otrzyma rzędy 100 obserwacji, które zostały zgrupowane w tym pojemniku. Mam część tego celu ukończoną. Moja MWE jest poniżej:

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) 

Kiedy uruchomić ten kod i otworzyć go w przeglądarce internetowej, mogę otrzymać interaktywny wykres jak poniżej (zielone pole nie jest w działce; to nałożony do celów informacyjnych):

enter image description here

Gdybym kliknij na sześciokąt w środku zielonego pola, prawidłowa hexID 40 i counts z 3 są wypisywane na konsoli. W tym momencie chciałbym uzyskać 3 wiersze oryginalnej ramki danych, które zostały umieszczone w tym sześciokątnym pojemniku.

wiem, jak to zrobić w R poza funkcją onRender() pakietu htmlwidgets za pomocą funkcji base::attr. Na przykład, można wykonać następujące czynności:

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

i odbierać następujące poprawnych 3 punkty danych, które zostały wprowadzone w tym pojemniku Kliknąłem na:

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

pracuję z dużo większych zbiorów danych niż w ten MWE. Z tego powodu, moim zamiarem użycia funkcji base:attr było zapobieganie przemieszczaniu się coraz większej ramki danych. Nie jestem jednak pewien, jak przetłumaczyć funkcję funkcji base::attr, aby uzyskać dostęp do odpowiednich wierszy punktów danych, które występują w klikniętym koszu sześciokątnym w kodzie JavaScript onRender(). Dodałem obiekt pS$data do kodu JavaScript , ale nadal mam problem.

Każda rada byłaby szczerze doceniona!

Odpowiedz

2

Można dodać kolumnę, która dla każdego rzędu ma identyfikator hexbin należy ona w swojej bindata:

bindata$hex <- [email protected] 

można następnie przekazać go do onRender funkcji i filtrów wierszy, gdy użytkownik kliknie sześciokąt:

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

Dziękuję za pomoc! Zdaję sobie sprawę, że brakowało mi przewidywania i nadmiernego uproszczenia mojego MWE, więc istnieje rozwiązanie (jak pokazałeś), które nie wymaga użycia base :: attr(). Rozwiązanie może być nadal pomocne dla mnie i innych osób. Napisałem lepszy MWE, który, mam nadzieję, ukazuje wyraźniej, dlaczego wciąż czuję się zablokowany przez bazę :: attr() i dlaczego nie sądzę, aby rozwiązanie tutaj działało w tym przypadku. Opublikowalem to w wersji 2 (http://stackoverflow.com/questions/42460061/retrieving-r-object-attributes-in-javascript-part-2). Dziękuję Ci. – luckButtered

+1

Mam coś, co ta sama strategia będzie działać dla części 2, napisałem rozwiązanie, które z nadzieją działa na twoim pełnym przykładzie. – NicE

Powiązane problemy