2017-02-25 5 views
4

이전에 비슷한 질문을 게시했습니다 (Retrieving R object attributes in JavaScript). 그 이전 게시물에서, 나는 나의 MWE를 단순화했다. 그래서 나는 불행하게도 나의 실제 문제에 실제로 적용되지 않는다. 여기에서는 JavaScript에서 R 객체 속성을 검색해야하는 이유를 보여줍니다 (다른 옵션이없는 경우는 제외).자바 스크립트에서 R 객체 속성 검색 - 제 2 부

나는 100 개의 관측치를 가진 5 변수 데이터 세트를 가지고 있습니다. 나는 육각형 비닝을 사용하고 산점도 매트릭스를 만들었다. 10 개의 산점도는 각각 12-18 개의 육각형 사이에 있습니다.

attr(hexdf, "cID") <- [email protected] 
: 모든 10 산점도의 육각형 쓰레기통 각에있는 100 개 관찰의 행을 절약하기 위해, 나는베이스 : 아래의 코드에서 R.에서 ATTR 기능을 사용, 이것은에서 수행됩니다

육각형 비닝의 대화 형 R Plotly 객체를 만들려고합니다. 사용자가 주어진 육각형 빈 (scatterplot과 관계없이)을 클릭하면 해당 bin으로 그룹화 된 100 개의 관측 행을 얻을 수 있습니다. . 나는이 목표의 일부를 완료했다. 아래 그림과 같이

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), C=rnorm(100), D=rnorm(100), E=rnorm(100)) 
bindata$ID <- as.character(bindata$ID) 

maxVal = max(abs(bindata[,2:6])) 
maxRange = c(-1*maxVal, maxVal) 

my_fn <- function(data, mapping, ...){ 
    x = data[,c(as.character(mapping$x))] 
    y = data[,c(as.character(mapping$y))] 
    h <- hexbin(x=x, y=y, xbins=5, shape=1, IDs=TRUE, xbnds=maxRange, ybnds=maxRange) 
    hexdf <- data.frame (hcell2xy (h), hexID = [email protected], counts = [email protected]) 
    attr(hexdf, "cID") <- [email protected] 
    p <- ggplot(hexdf, aes(x=x, y=y, fill = counts, hexID=hexID)) + geom_hex(stat="identity") 
    p 
} 

p <- ggpairs(bindata[,2:6], lower = list(continuous = my_fn)) 
pS <- p 
for(i in 2:p$nrow) { 
    for(j in 1:(i-1)) { 
    pS[i,j] <- p[i,j] + 
     coord_cartesian(xlim = c(maxRange[1], maxRange[2]), ylim = c(maxRange[1], maxRange[2])) 
    } 
} 

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) { 
      el = el; 
      x=x; 
      var data = data[0]; 
      console.log(el) 
      console.log(x) 
      console.log(data) 

      myLength = Math.sqrt(document.getElementsByClassName('cartesianlayer')[0].childNodes.length); 
      console.log(myLength) 

      el.on('plotly_click', function(e) { 
      console.log(e.points[0]) 
      xVar = (e.points[0].xaxis._id).replace(/[^0-9]/g,'') 
      if (xVar.length == 0) xVar = 1 
      yVar = (e.points[0].yaxis._id).replace(/[^0-9]/g,'') 
      if (yVar.length == 0) yVar = 1 
      myX = myLength + 1 - (yVar - myLength * (xVar - 1)) 
      myY = xVar 

      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(myX) 
      console.log(myY) 
      console.log(hexID) 
      console.log(counts) 
      })} 
      ", data = pS[5,2]$data) 

이 이미지를 만듭니다 : 내 MWE은 아래 예를 들어

Scatterplot matrix of hexagon binning

, 육각형 녹색 상자에 강조에 내가 클릭하면 내가 결정할 수있는 부가 적 줄거리 ("myX"및 "myY"), 클릭 된 육각형의 ID ("hexID") 및 해당 육각형으로 비닝 된 관측점의 수 ("개수")에서 발생했습니다. 이 특정 육각형에 대해 myX = 5, myY = 2, hexID = 39 및 counts = 1입니다. 따라서 사용자는 다섯 번째 행과 두 번째 열의 산점도에서 ID39가있는 육각형을 클릭하고 비닝 한 1 개의 데이터 포인트가 있어야합니다.

내가하는 onRender() 함수를두고 단순히 R에 다음 코드를 입력하는 경우 : 다음

myX <- 5 
myY <- 2 
hexID <- 39 
obsns <- which(attr(pS[myX,myY]$data, "cID")==hexID) 
dat <- bindata[obsns,] 

을 그으로 비닝 된 하나 개의 관찰을 포함하는 데이터 프레임의 행을 획득 할 수 클릭 한 육각형 :

> dat 
    ID  A   B  C   D  E 
95 ID95 1.586833 -1.208083 1.778429 -0.1101588 3.810277 

제 마지막 문제는 간단합니다. "obsns"객체를 얻기 위해 onRender() 함수 내에서 base :: attr() 함수를 사용하는 방법을 파악할 수 없습니다. 이 문제에 대한 해결 방법이 있습니까? 아니면 다른 고려해야 할 접근법이 있습니까? 어떤 아이디어/조언 주셔서 감사합니다!

답변

1

plotly에서 16 진수 ID에 액세스 할 수 있는지 또는이 데이터를 어딘가에 보관하는지 여부가 확실하지 않으므로 한 가지 옵션으로 용도에 필요한 모든 데이터가 onRender 기능에 전달됩니다.

먼저 hexplot 당 bindata dataframe에 열을 추가 할 수 있습니다,라는 mX-mY (당신은 MX를 교체하고 내 각 열에 대한 가치에 의해 곳), 즉, 각 관찰 그 플롯이 속한 hexbin를 개최합니다 :

for(i in 2:5) { 
    for(j in 1:4) { 
    bindata[[paste(i,j,sep="-")]] <- attr(pS[i,j]$data, "cID") 
    } 
} 
그런 다음 onRender 기능에 bindata를 전달할 수 whever 해당 hexbin에 속하는 관찰 bindata에서 해당 열에서 확인, 플롯 중 하나에 육각 클릭

:

ggPS %>% onRender(" 
       function(el, x, data) { 

       myLength = Math.sqrt(document.getElementsByClassName('cartesianlayer')[0].childNodes.length); 


       el.on('plotly_click', function(e) { 
       xVar = (e.points[0].xaxis._id).replace(/[^0-9]/g,'') 
       if (xVar.length == 0) xVar = 1 
       yVar = (e.points[0].yaxis._id).replace(/[^0-9]/g,'') 
       if (yVar.length == 0) yVar = 1 
       myX = myLength + 1 - (yVar - myLength * (xVar - 1)) 
       myY = xVar 

       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[myX+'-'+myY]==hexID) selected_rows.push(row); 
       }); 
       console.log(selected_rows); 

       })} 
       ", data = bindata) 
+0

이 점을 지적 해 주셔서 감사합니다.나는 오랫동안이 작업을 해왔고, 이전에 한 subplot에 대해 보여준 후에도 attr()을 사용할 수 있다고 생각하지 않았습니다. 놀랍게도이 방법은 onRender() 함수에서 지연을 일으키지 않는 것 같습니다. 내 데이터 프레임 크기를 100에서 50,000으로 변경했으며 주어진 육각형을 클릭하면 개별적인 관측치를 얻기 위해 즉시 50,000의 큰 데이터 프레임을 구문 분석 할 수 있습니다. 나는 자바 스크립트가 내가 예상했던 것보다 빨리 일어날 수 있다고 생각한다 (나는 주로 R을 사용한다)? – luckButtered