RCall.jl
RCall.jl copied to clipboard
Showing R plots in Juno plot pane
Is it possible to show ggplot2 plots in the Juno plot pane?
using RCall, DataFrames
@rlibrary ggplot2
df = DataFrame(x=rand(10), y=rand(10))
ggplot(df) + geom_point(aes(x=:x, y=:y))
This plot is shown in a Jupyter notebook, but when run in Juno, it is shown in an R plot window.
Instead of cross-posting in the Juno repo, I am pinging @pfitzseb. If you give me hints where to start this, I would try to tackle this myself.
You need overloads for the correct Base.show method (see here for some docs on that). I didn't see any Base.show overloads in this package, so I have no idea how displaying stuff in Jupyter notebooks works.
thanks for the hint. I'll see how far I get.
As far as Juno is concerned, probably this: https://github.com/JuliaInterop/RCall.jl/blob/master/src/ijulia.jl
I think I got it to work.
using RCall, DataFrames
@rlibrary ggplot2
df_string = DataFrame(x = randn(100), y=randn(100), z1=rand(["a"; "b"], 100), z2=rand(["darkorange"; "lightblue"], 100))
plt = ggplot(df_string) + geom_point(aes(x=:x, y=:y, color=:z2)) # works with standard colors
using ImageShow
using FileIO
rdevicefun(m::MIME"image/png") = @rget png
#rdevicefun(m::MIME"image/svg+xml", f) = R"svg($f)"
ext(::MIME"image/png") = ".png"
#ext(::MIME"image/svg+xml") = ".svg"
function Base.show(io::IO, m::MIME"image/png", plt::RObject)
f = tempname() * ext(m)
width, height = get(io, :juno_plotsize, [100, 100])
R"""
png($f, width=$width, height=$height, units="px", pointsize=20)
show($plt) # plot(rnorm(10), rnorm(10))
dev.off()
"""
show(io, m, load(f))
end
plt
Before I put this into a PR I need some advice
- Is it a good idea to use use
width, height = get(io, :juno_plotsize, [100, 100])because the function might be useful outside Juno. Do you have suggestion for improvement? - Do you think the tmp-file is a good solution?
- Since R plots are pointers, I couldn't figure out which type they actually are. Could someone tell be what I can use instead of
::RObject?
Is it a good idea to use use width,
height = get(io, :juno_plotsize, [100, 100])because the function might be useful outside Juno. Do you have suggestion for improvement?
Would probably make sense to use the defaults that are already in place instead of [100, 100].
Do you think the tmp-file is a good solution?
Not really, but it might be the easiest solution for now (and is already what is used for IJulia display, so whatever).
Since R plots are pointers, I couldn't figure out which type they actually are. Could someone tell be what I can use instead of
::RObject?
You probably can't do any better, but for correctness you'll need to figure out a runtime check for whether you have a R-plot, and put that into
Base.showable(m::MIME"image/png", plt::RObject) = is_a_plot(plt)
so the display system does the right thing.
Thank you for your help!
Regarding
You probably can't do any better, but for correctness you'll need to figure out a runtime check for whether you have a R-plot, and put that into
Base.showable(m::MIME"image/png", plt::RObject) = is_a_plot(plt)
so the display system does the right thing.
probably some of the RCall contributors can help me out with this?
EDIT:
I found the is.ggplot() function in R. And it seems, that one cannot actually save a base plot and show it again.
So the code above actually doesn't work for base plots.
Now that I understand that R-base plots cannot be captured ex-post, I start to understand what the code in ijulia.jl does.
- It resets the default
deviceso that plots are automatically saved tofile - At the end of each cell it checks if there is a plot open (post-execute hook)
- If there is a plot,
showit, close thedeviceand remove thefile
Are there such things like post-execute hooks in Juno as well?
The two options I see are
- Use the current implementation for
ggplot2only
Base.showable(m::MIME"image/png", plt::RObject) = R"is.ggplot($plt)"
- Follow the
IJuliastrategy and implement post-execute hooks
What could be done to show rcall plots in julia-vscode?