【问题标题】:Retrieving R object attributes in JavaScript在 JavaScript 中检索 R 对象属性
【发布时间】:2017-07-11 20:17:29
【问题描述】:

我有一个包含 100 个观测值的双变量数据集。我使用了六边形分箱,最终得到了 26 个六边形分箱。为了保存 26 个六边形 bin 中的每一个中的 100 个观测值的行,我在 R 中使用了 base::attr 函数。在下面的代码中,这是在以下位置完成的:

attr(hexdf, "cID") <- h@cID

我正在尝试创建六边形分箱的交互式 R Plotly 对象,以便如果用户单击给定的六边形箱,他们将获得分组到该箱中的 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 = h@cell, counts = h@count)
attr(hexdf, "cID") <- h@cID
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)

当我运行此代码并在 Web 浏览器中打开它时,我会得到一个如下所示的交互式绘图(绿色框不在绘图中;它被叠加用于解释目的):

如果我点击绿色框内的六边形,正确的hexID 40 和counts 3 将打印到控制台。此时,我想获取放入那个六边形bin的原始数据框的3行。

我知道如何使用base::attr 函数在htmlwidgets 包的onRender() 函数之外的R 中执行此操作。例如,我可以执行以下操作:

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

并收到以下正确的 3 个数据点,这些数据点被放入我点击的那个 bin:

     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 函数的功能,以便我可以访问出现在 onRender() JavaScript 代码中单击的六边形 bin 中的适当数据点行。我确实将pS$data 对象包含到onRender() JavaScript 代码中,但仍然卡住了。

任何建议将不胜感激!

【问题讨论】:

    标签: javascript r plotly htmlwidgets onrender


    【解决方案1】:

    您可以添加一列,该列的每一行都有它在您的 bindata 中所属的 hexbin 的 ID:

    bindata$hex <- h@cID
    

    然后您可以将其传递给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)
    

    【讨论】:

    • 感谢您的帮助!我意识到我缺乏远见并且过分简化了我的 MWE,因此有一个不需要使用 base::attr() 的解决方案(如您所示)。该解决方案仍然对我和其他人有帮助。我刚刚写了一个更好的 MWE,我希望能更清楚地说明为什么我仍然坚持使用 base::attr() 以及为什么我认为这里的解决方案不适用于这种情况。我将其发布在第 2 部分版本 (stackoverflow.com/questions/42460061/…) 中。谢谢。
    • 我认为相同的策略适用于第 2 部分,我发布了一个解决方案,希望适用于您的完整示例。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-09-24
    • 2019-05-30
    • 2012-12-24
    • 2012-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多