Подтвердить что ты не робот

Комбинирование ggplot2 и d3 (учебник gridSVG приводит к неинтерактивному изображению)

Я следую простому учебному пособию по интеграции ggplot2 и d3. Я специально работаю над методом 2 на этом учебном сайте (http://timelyportfolio.github.io/gridSVG_intro/). Я пытаюсь воспроизвести интерактивный сюжет (это последний сюжет на этой странице).

Я использовал один и тот же синтаксис и ввел его в файл .R следующим образом:

library(gridSVG)
library(ggplot2)
library(XML)
library(rjson)

set.seed(955)
dat <- data.frame(cond = rep(c("A", "B"), each=10), xvar = 1:20 + rnorm(20,sd=3), yvar = 1:20 + rnorm(20,sd=3))

g4 = ggplot(dat, aes(x=xvar, y=yvar)) + geom_smooth() + geom_point(shape=19, aes(color = cond), size=5)
g4
g4.svg <- grid.export("plot1.svg",addClasses=TRUE)

cat(saveXML(g4.svg$svg))

cat(
  '<script> ourdata=',
  rjson::toJSON(apply(g4$data,MARGIN=1,FUN=function(x)return(list(x)))),
  '</script>'
)

cat(
  '<script> dataToBind = ',
  'd3.entries(ourdata.map(function(d,i) {return d[0]}))',
  '</script>'
)

cat(
  '<script>\n',
  'scatterPoints = d3.select(".points").selectAll("use");\n',
  'scatterPoints.data(dataToBind)',
  '</script>\n'
)

cat('<script>\n',
    'scatterPoints  
    .on("mouseover", function(d) {      
    //Create the tooltip label
    var tooltip = d3.select(this.parentNode).append("g");
    tooltip
    .attr("id","tooltip")
    .attr("transform","translate("+(d3.select(this).attr("x")+10)+","+d3.select(this).attr("y")+")")
    .append("rect")
    .attr("stroke","white")
    .attr("stroke-opacity",.5)
    .attr("fill","white")
    .attr("fill-opacity",.5)
    .attr("height",30)
    .attr("width",50)
    .attr("rx",5)
    .attr("x",2)
    .attr("y",5);
    tooltip.append("text")
    .attr("transform","scale(1,-1)")
    .attr("x",5)
    .attr("y",-22)
    .attr("text-anchor","start")
    .attr("stroke","gray")
    .attr("fill","gray")
    .attr("fill-opacity",1)
    .attr("opacity",1)
    .text("x:" + Math.round(d.value.xvar*100)/100);
    tooltip.append("text")
    .attr("transform","scale(1,-1)")
    .attr("x",5)
    .attr("y",-10)
    .attr("text-anchor","start")
    .attr("stroke","gray")
    .attr("fill","gray")      
    .attr("fill-opacity",1)
    .attr("opacity",1)
    .text("y:" + Math.round(d.value.yvar*100)/100);
    })              
    .on("mouseout", function(d) {       
    d3.select("#tooltip").remove();  
    });',
'</script>'
)

Единственным результатом, который я получаю от этого script, является файл plot1.svg. Однако, когда я открываю это в браузере (попробовал Safari и Google Chrome), это застойная версия изображения.

Я отправил бы электронное письмо автору самому. Но эта контактная информация недоступна. Он предназначен для простого учебника, поэтому я надеюсь, что это простое решение!

Я новичок в этом интерактивном компоненте. Тем не менее, я последовал инструкциям шаг за шагом и не знал, что я, возможно, пренебрег. Любая поддержка или информация, имеющие отношение к решению этой проблемы, будут очень оценены!

4b9b3361

Ответ 1

редактирует

Итак, я закончил установку R, чтобы увидеть, где мой оригинальный ответ поступил не так. Я был близко. Я пропустил вызов saveXML и как @arvi1000 указал, что я не был источником d3. Здесь приведен полный пример. Я просто запустил его с помощью R 3.2.3, и он создаст myAwesomePlot.html в вашем рабочем каталоге:

library(gridSVG)
library(ggplot2)
library(XML)
library(rjson)

set.seed(955)
dat <- data.frame(cond = rep(c("A", "B"), each=10), xvar = 1:20 + rnorm(20,sd=3), yvar = 1:20 + rnorm(20,sd=3))

g4 = ggplot(dat, aes(x=xvar, y=yvar)) + geom_smooth() + geom_point(shape=19, aes(color = cond), size=5)

# what does this line do?  It writes the SVG to the file "plot1.svg"?
g4.svg <- grid.export("", addClasses=TRUE)

# create a valid html file
cat("<html><head><script src='http://d3js.org/d3.v3.min.js'></script></head><body>", file="myAwesomePlot.html")

# I'm assuming this gets the svg content and can write it to a file
cat(saveXML(g4.svg$svg), file="myAwesomePlot.html", append=TRUE)

cat(
'<script> ourdata=',
rjson::toJSON(apply(g4$data,MARGIN=1,FUN=function(x)return(list(x)))),
'</script>', file="myAwesomePlot.html", append=TRUE
)

cat(
  '<script> dataToBind = ',
  'd3.entries(ourdata.map(function(d,i) {return d[0]}))',
  '</script>'
  , file="myAwesomePlot.html", append=TRUE)

cat(
  '<script>\n',
  'scatterPoints = d3.select(".points").selectAll("use");\n',
  'scatterPoints.data(dataToBind)',
  '</script>\n'
  , file="myAwesomePlot.html", append=TRUE)

cat('<script>\n',
    'scatterPoints  
    .on("mouseover", function(d) {      
    //Create the tooltip label
    var tooltip = d3.select(this.parentNode).append("g");
    tooltip
    .attr("id","tooltip")
    .attr("transform","translate("+(d3.select(this).attr("x")+10)+","+d3.select(this).attr("y")+")")
    .append("rect")
    .attr("stroke","white")
    .attr("stroke-opacity",.5)
    .attr("fill","white")
    .attr("fill-opacity",.5)
    .attr("height",30)
    .attr("width",50)
    .attr("rx",5)
    .attr("x",2)
    .attr("y",5);
    tooltip.append("text")
    .attr("transform","scale(1,-1)")
    .attr("x",5)
    .attr("y",-22)
    .attr("text-anchor","start")
    .attr("stroke","gray")
    .attr("fill","gray")
    .attr("fill-opacity",1)
    .attr("opacity",1)
    .text("x:" + Math.round(d.value.xvar*100)/100);
    tooltip.append("text")
    .attr("transform","scale(1,-1)")
    .attr("x",5)
    .attr("y",-10)
    .attr("text-anchor","start")
    .attr("stroke","gray")
    .attr("fill","gray")      
    .attr("fill-opacity",1)
    .attr("opacity",1)
    .text("y:" + Math.round(d.value.yvar*100)/100);
    })              
    .on("mouseout", function(d) {       
    d3.select("#tooltip").remove();  
    });',
'</script>'
, file="myAwesomePlot.html", append=TRUE)

# close out file
cat("</body></html>", file="myAwesomePlot.html", append=TRUE)

Оригинальный ответ

Прошло некоторое время с тех пор, как я выполнил любое программирование R, но те функции cat выглядят не так. Они будут писать стандартно, а не в файл. Я предполагаю, что grid.export записывает только файл svg и все остальное отбрасывается. С первого взгляда я предполагаю, что вы должны запустить этот код как:

R myRCode.R > outPutFile.svg

Итак, stdout перенаправляется в файл.

Я бы попытался немного перестроить код и написать все в файл html явно:

library(gridSVG)
library(ggplot2)
library(XML)
library(rjson)

set.seed(955)
dat <- data.frame(cond = rep(c("A", "B"), each=10), xvar = 1:20 + rnorm(20,sd=3), yvar = 1:20 + rnorm(20,sd=3))

g4 = ggplot(dat, aes(x=xvar, y=yvar)) + geom_smooth() + geom_point(shape=19, aes(color = cond), size=5)
g4

// what does this line do?  It writes the SVG to the file "plot1.svg"?
g4.svg <- grid.export("plot1.svg",addClasses=TRUE)

// create a valid html file
cat("<html><head></head><body>", file="myAwesomePlot.html")

// I'm assuming this gets the svg content and can write it to a file
cat(g4.svg$svg, file="myAwesomePlot.html")

cat(
  '<script> ourdata=',
  rjson::toJSON(apply(g4$data,MARGIN=1,FUN=function(x)return(list(x)))),
  '</script>', file="myAwesomePlot.html"
)

// etc, rest of JavaScript

// close out file
cat("</body></html>", file="myAwesomePlot.html")

Ответ 2

  • Вам не хватает ссылки на библиотеку D3.js!
  • cat, как и у вас, в обычном R script, просто выводит на консоль, как сказал @Mark.

Чтобы решить 1) ваш окончательный html-документ должен содержать: <script src="http://d3js.org/d3.v3.min.js"></script> или эквивалент.

Чтобы решить 2), вы можете работать с файлом Rmarkdown.Rmd и помещать все, что у вас есть в куске.

В файле с расширением .Rmd запустите фрагмент с помощью этой строки:

```{r, echo=FALSE, results='asis', warning=FALSE, message=FALSE}

далее, убедитесь, что вы включили библиотеку D3 в эту строку:

cat('<script src="http://d3js.org/d3.v3.min.js"></script>')

затем добавьте весь свой код выше, а затем, чтобы закончить кусок:

```

Если вы делаете это внутри Rstudio, вы можете нажать "Вязать HTML". В противном случае вы можете использовать knitr::knit2html или rmarkdown::render с консоли или в другом .R script)

Ответ 3

Если вам не нравится предложение @arvi1000 использовать knitr (что является хорошим), вы можете использовать sink(file = "myfile.html") перед первым оператором cat(), чтобы записать весь вывод в myfile.html. В конце просто добавьте инструкцию sink(), чтобы начать запись на стандартный вывод.

Как и @arvi1000, вам также не хватает ссылки на библиотеку D3.js. Следуя их указаниям, положите cat('<script src="http://d3js.org/d3.v3.min.js"></script>') в качестве своего первого оператора cat(). Вам также может потребоваться следовать рекомендациям @Mark о создании допустимого HTML файла.

Честно говоря, самый простой способ - использовать knitr. Я включил содержимое действительного файла .Rmd, который будет создавать график D3.js. Просто запустите knitr::knit2html() в файле .Rmd, содержащем следующий код. Я добавил несколько комментариев с моей лучшей интерпретацией того, что происходит (я никогда не делал ggplot для D3.js, поэтому для меня это был классный опыт!)

```{r echo = FALSE, message = FALSE, fig.keep = 'none'}
library(gridSVG)
library(ggplot2)
library(XML)
library(rjson)

# create a plot with some fake data

set.seed(955)
dat <- data.frame(cond = rep(c("A", "B"), each=10), xvar = 1:20 + rnorm(20,sd=3), yvar = 1:20 + rnorm(20,sd=3))

g4 = ggplot(dat, aes(x=xvar, y=yvar)) + geom_smooth() + geom_point(shape=19, aes(color = cond), size=5)

# you need to print the plot in order to capture it with grid.export
g4
# exporting the plot to a .svg file
g4.svg <- grid.export("plot1.svg",addClasses=TRUE)
```

```{r, echo=FALSE, results='asis', warning=FALSE, message=FALSE}

# load the d3.js script
cat('<script src="http://d3js.org/d3.v3.min.js"></script>')

# convert the svg file to an XML string and print it 
cat(saveXML(g4.svg$svg))

# looks like you convert the ggplot object data to JSON for use by d3.js
# looks like the aesthetics are included here? I don't seem them defined 
# anywhere else
cat(
  '<script> ourdata=',
  rjson::toJSON(apply(g4$data,MARGIN=1,FUN=function(x)return(list(x)))),
  '</script>'
)

# d3.js data definition
cat(
  '<script> dataToBind = ',
  'd3.entries(ourdata.map(function(d,i) {return d[0]}))',
  '</script>'
)

# d3.js scatter plot
cat(
  '<script>\n',
  'scatterPoints = d3.select(".points").selectAll("use");\n',
  'scatterPoints.data(dataToBind)',
  '</script>\n'
)

# d3.js code to support the hover tooltips (hover over a point on the plot)
# this is apparently ALL for the tooltip
cat('<script>\n',
    'scatterPoints  
    .on("mouseover", function(d) {      
    //Create the tooltip label
    var tooltip = d3.select(this.parentNode).append("g");
    tooltip
    .attr("id","tooltip")
    .attr("transform","translate("+(d3.select(this).attr("x")+10)+","+d3.select(this).attr("y")+")")
    .append("rect")
    .attr("stroke","white")
    .attr("stroke-opacity",.5)
    .attr("fill","white")
    .attr("fill-opacity",.5)
    .attr("height",30)
    .attr("width",50)
    .attr("rx",5)
    .attr("x",2)
    .attr("y",5);
    tooltip.append("text")
    .attr("transform","scale(1,-1)")
    .attr("x",5)
    .attr("y",-22)
    .attr("text-anchor","start")
    .attr("stroke","gray")
    .attr("fill","gray")
    .attr("fill-opacity",1)
    .attr("opacity",1)
    .text("x:" + Math.round(d.value.xvar*100)/100);
    tooltip.append("text")
    .attr("transform","scale(1,-1)")
    .attr("x",5)
    .attr("y",-10)
    .attr("text-anchor","start")
    .attr("stroke","gray")
    .attr("fill","gray")      
    .attr("fill-opacity",1)
    .attr("opacity",1)
    .text("y:" + Math.round(d.value.yvar*100)/100);
    })              
    .on("mouseout", function(d) {       
    d3.select("#tooltip").remove();  
    });',
'</script>'
)
```