2017-02-22 38 views
6

У меня есть двумерный набор данных со 100 наблюдениями. Я использовал шестиугольное биннинг и закончил с 26 шестиугольными бункерами. Для того, чтобы сохранить строки 100 наблюдений, которые находятся в каждом из 26 шестигранных бункеров, я использовал функцию base::attr в R. В приведенном ниже коде, это делается на:Получение атрибутов объекта R в JavaScript

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

Я пытаюсь создать интерактивный объект Rбиннинга шестиугольника, так что если пользователь должен щелкнуть по данному шестиугольному бункеру, они получат строки из 100 наблюдений, которые были сгруппированы в этот бит. У меня есть часть этой цели. Мой MWE ниже:

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) 

Когда я запускаю этот код и открыть его в веб-браузере, я получаю интерактивный сюжет, как показано ниже (зеленая коробка не в заговоре, он накладывается для пояснительных целей):

enter image description here

Если я нажимаю на шестиугольника внутри зеленой коробке, правильный hexID 40 и counts из 3 распечатываются на консоли. На этом этапе я хотел бы получить 3 строки исходного кадра данных, которые были помещены в этот шестиугольник.

Я знаю, как это сделать в R за пределами функции onRender()htmlwidgets с помощью функции base::attr. Например, я могу сделать следующее:

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

И получить следующие правильные 3 точек данных, которые были введены в этот бункер, я нажал на:

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

Я работаю с гораздо большими наборами данных, чем в это MWE. По этой причине мое намерение использовать функцию base:attr состояло в том, чтобы предотвратить все больший фрейм данных. Тем не менее, я не уверен, как перевести функциональность функции base::attr, чтобы я мог получить доступ к соответствующим строкам данных, которые встречаются в щелкнутой шестиугольной ячейке в коде JavaScript onRender(). Я включил объект pS$data в код JavaScript onRender(), но я все еще застрял.

Любые советы были бы искренне оценены!

ответ

2

Вы можете добавить столбец, который для каждой строки имеет идентификатор hexbin она принадлежит в вашем bindata:

bindata$hex <- [email protected] 

Вы можете затем передать его в onRender функции и фильтрации строк, когда пользователи нажимают на шестиугольник:

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

Благодарим за помощь! Я понимаю, что мне не хватало предвидения и упростило мой MWE, так что есть решение (как вы показали), которое не требует использования base :: attr(). Решение может быть полезным для меня и для других. Я просто написал лучший MWE, который, я надеюсь, более четко показывает, почему я чувствую себя застрявшим с базой :: attr(), и почему я не думаю, что решение здесь будет работать для этого случая. Я опубликовал это в версии части 2 (http://stackoverflow.com/questions/42460061/retrieving-r-object-attributes-in-javascript-part-2). Спасибо. – luckButtered

+1

У меня такая же стратегия будет работать для части 2, я опубликовал решение, которое, надеюсь, будет работать на вашем полном примере. – NicE