Creating plot using plotnine of python from R through reticulate - reticulate

Being a R user, I am learning to incorporate python command in R through reticulate, I tried plotting graph using the plotnine package in R but it returned the following error, can anyone help?
library(reticulate)
library(ggplot2)
pd <- import('pandas', as='pd',convert=FALSE)
p9 <- import('plotnine')
mpg_py <- r_to_py(mpg,convert=FALSE)
mpg_pd <- pd$DataFrame(data=mpg_py)
p9$ggplot(data=mpg_pd,p9$aes(x='displ',y='cty'))
# Error in py_call_impl(callable, dots$args, dots$keywords) :
# AttributeError: 'NoneType' object has no attribute 'f_locals'

The answer to this question pointed me down a promising path for this error. It seems the error is due to an issue in the patsy package that handles the namespace/scoping for plotnine. By default the plotnine.ggplot constructor creates an environment to know where to get the plotting data and aesthetics. So adapting from the linked answer, here's a potential solution where we import the patsy package and use the environment parameter in the ggplot function to pass an evaluation environment (docs).
library(reticulate)
library(ggplot2)
pd = import('pandas',convert=F)
p9 = import('plotnine')
# new imports
patsy = import('patsy')
# import to be able to show in RStudio (see issue here: https://github.com/rstudio/rstudio/issues/4978)
matplotlib = import('matplotlib')
matplotlib$use('tkAgg')
plt = import('matplotlib.pyplot')
mpg_py <- r_to_py(mpg,convert=FALSE)
mpg_pd <- pd$DataFrame(data=mpg_py)
plot_py = p9$ggplot(mpg_pd,p9$aes(x='displ',y='cty'),
# new code (-1 was the only value that didn't throw an error)
environment = patsy$EvalEnvironment$capture(eval_env=as.integer(-1)))
print(class(plot_py)) # "plotnine.ggplot.ggplot" "python.builtin.object"
# Actually show the plot
plot_py
plt$show()

Related

plotRGB error when calling plot_map() in rayshader package in R

I'm trying to use the rayshader package in R to plot elevation data, but I'm getting an error when I call the plot_map() function. I can't even get the example to run without running into the following error. Any ideas on how to get this function to run?
error in evaluating the argument 'x' in selecting a method for function 'plotRGB': unused argument (asp = 1)
Here is the example code that I am calling.
library(rayshader)
#Here, I load a map with the raster package.
loadzip = tempfile()
download.file("https://tylermw.com/data/dem_01.tif.zip", loadzip)
localtif = raster::raster(unzip(loadzip, "dem_01.tif"))
unlink(loadzip)
#And convert it to a matrix:
elmat = raster_to_matrix(localtif)
#We use another one of rayshader's built-in textures:
elmat %>%
sphere_shade(texture = "desert") %>%
plot_map()

Why graphics::plot call on hexbin object throws an error?

In short: I'm trying to run this hexbin example which works fine unless I replace plot with graphics::plot. The latter throws following error:
> graphics::plot(bin, main="" , colramp=my_colors , legend=F )
Error in as.double(y) :
cannot coerce type 'S4' to vector of type 'double'
How to make this work?
Wider context why I need this work this way. I contribute to the clojisr project which brings R to Clojure using RServe. There is an option to require R packages and create corresponding Clojure functions. This works well (see this or this). The underlying calls to R are in the form of {package::symbol} for everything.
Class hexbin is an S4 class and the package defines an S4 generic and a method for plot. (The source code is here). There is no S4 generic for plot in the graphics package namespace, only an S3 generic.
The solution is therefore very simple:
hexbin::plot(bin, main="" , colramp=my_colors , legend=F )
Here's a reprex to prove it:
library(hexbin)
library(RColorBrewer)
# Create data
x <- rnorm(mean=1.5, 5000)
y <- rnorm(mean=1.6, 5000)
# Make the plot
bin<-hexbin(x, y, xbins=40)
my_colors=colorRampPalette(rev(brewer.pal(11,'Spectral')))
hexbin::plot(bin, main="" , colramp=my_colors , legend=F )
Created on 2020-02-17 by the reprex package (v0.3.0)

ggnet2 : Error: Each variable must be a 1d atomic vector or list

I am trying to use ggnet2 for visualizing a network analysis, but have run into an error with the vignette.
I can generate a random network,
library(ggnet2)
library(network)
library(sna)
library(ggplot2)
net = rgraph(10, mode = "graph", tprob = 0.5)
net = network(net, directed = FALSE)
# vertex names
network.vertex.names(net) = letters[1:10]
With an output that looks reasonable
>net
Network attributes:
vertices = 10
directed = FALSE
hyper = FALSE
loops = FALSE
multiple = FALSE
bipartite = FALSE
total edges= 28
missing edges= 0
non-missing edges= 28
Vertex attribute names:
vertex.names
No edge attributes
However, when I try to run..
ggnet2(net)
I get an error
Error: Each variable must be a 1d atomic vector or list. Problem variables: 'x', 'y', 'xend', 'yend'
I am not clear on how this error is arising in the vignette as net is a list, and all variables within it are lists. I have checked to ensure that I have all the necessary packages and they are up-to-date as well as the most recent R version.
I just tried ggnetwork and seem to get a similar error.
Any thoughts on why this errors is arising?
The error message says
Error: Each variable must be a 1d atomic vector or list. Problem
variables: 'x', 'y', 'xend', 'yend'
If you do the following
library(ggnetwork)
net <- ggnetwork(net)
class(net$x)
you will find that x is a one column matrix. The same is true for your other components. So doing
net$x <- net$x[,1]
net$y <- net$y[,1]
net$xend <- net$xend[,1]
net$yend <- net$yend[,1]
will change these all to 1d atomic vectors and
ggplot(net, aes(x = x, y = y, xend = xend, yend = yend)) +
geom_edges(aes(linetype = "directed"), color = "grey50")
should work. You can read more about how to make ggnetwork work for prettier graphs.
I had the same issue following the tutorial at briatte.github.io/ggnet.
The issue went away after I updated the 'igraph', 'ggplot', 'intergraph', 'GGally' packages and installed the 'ggnetwork' from source:
install.packages("ggnetwork", type="source").
This was suggested here to fix another issue, but somehow it worked for me on this one. Perhaps you could give it a try.
I think I've found a solution for the issue, at least on my machine. I'm running R 3.4.3 on Win 10, but this is probably not platform-related.
Until now I've had the CRAN version of GGally installed, along with network and sna, just as mentioned in the example, and this setup threw the exact same error mentioned above. I was confused as the original network object doesn't even have members like x, xend, etc. It turned out that these are in fact members of the ggnetwork object, which is created invisibly during the command ggnet() (ggnetwork vignette).
So I've tried installing ggnetwork: install.packages("ggnetwork") along with the source version of ggnet
(devtools::install_github("briatte/ggnet")).
ggnetwork was installed succesfully, but the package couldn't be loaded because it said that ggplot2 is not installed (which I've found strange because it's a package that I use on a daily basis as part of the tidyverse library).
ggnet installation failed for some reason related to packages being already loaded.
I've restarted the R session, tried loading ggnetwork again, which again failed for lack of ggplot2, so I installed ggplot2. I tried once again installing ggnet from source, (this time before any packages were loaded) and it worked.
So, to sum it up:
After restarting the R session:
install.packages("ggnetwork")
install.packages("ggplot2")
devtools::install_github("briatte/ggnet")
I don't know exactly which step did it, but afterwards the example script produced a graph plot, just as it was supposed to:
library(ggnetwork)
library(network)
library(sna)
library(ggnet)
net = rgraph(10, mode = "graph", tprob = 0.5)
net = network(net, directed = FALSE)
network.vertex.names(net) = letters[1:10]
ggnet2(net)

Pesky ggplot2 namespace conflict when using ggplot2 in package

I'm contributing to the qmethod R package, and I just wrote a function that creates a bunch of ggplot2 objects.
The function works fine, but builds and R CMD Check warns me that:
replacing previous import by ‘ggplot2::%+%’ when loading ‘qmethod’
I've looked at SE posts and #hadley's book but can't figure out the problem.
Here's the relevant parts of my NAMESPACE:
import("ggplot2",
"stringr")
import("psych")
importFrom("plyr","count")
importFrom("reshape2","melt")
importFrom("digest", "digest")
importFrom("RColorBrewer", "brewer.pal")
And here's part of my DESCRIPTION:
Imports:
digest,
psych,
knitr,
RColorBrewer,
stringr,
ggplot2,
plyr,
reshape2
The part where I call a ggplot2 function inside my function array.viz.R looks like this (and more):
g <- ggplot(
data = array.viz.data
,aes(
x = fsc # factor scores, always same variable bc dataframe is constructed for every factor array by above loop
,y = ycoord # just the random ycoord for viz
,ymax = max(ycoord)
,ymin = 0
#,label = item.wrapped # this for some reason causes an error
)
)
g <- g + geom_tile( # add background tiles
aes(
fill = item.sd
)
)
Ps.: you can find the entire current work here: https://github.com/maxheld83/qmethod/tree/array-viz
Pps.: I am aware that ggplot2 itself imports a bunch of the functions I also import (such as reshape2), so I have a hunch that that might be a problem.
Turns out, import("psych") is the offending package.
It seems to somehow export again ggplot::%+%, though I can't think of why that would be the case.
Anyway, the fix is:
importFrom("psych", "principal") # that's the function we were using

R package lattice won't plot if run using source()

I started using the lattice graphic package but I stumbled into a problem. I hope somebody can help me out.
I want to plot a histogram using the corresponding function.
Here is the file foo.r:
library("lattice")
data <- data.frame(c(1:2),c(2:3))
colnames(data) <- c("RT", "Type")
pdf("/tmp/baz.pdf")
histogram( ~ RT | factor(Type), data = data)
dev.off()
When I run this code using R --vanilla < foo.r it works all fine.
However, if I use a second file bar.r with
source("bar")
and run R --vanilla < bar.r the code produces an erroneous pdf file.
Now I found out that source("bar", echo=TRUE) solves the problem. What is going on here? Is this a bug or am I missing something?
I'm using R version 2.13.1 (2011-07-08) with lattice_0.19-30
It is in the FAQ for R -- you need print() around the lattice function you call:
7.22 Why do lattice/trellis graphics not work?
The most likely reason is that you forgot to tell R to display the
graph. Lattice functions such as xyplot() create a graph object, but
do not display it (the same is true of ggplot2 graphics, and Trellis
graphics in S-Plus). The print() method for the graph object produces
the actual display. When you use these functions interactively at the
command line, the result is automatically printed, but in source() or
inside your own functions you will need an explicit print() statement.
Example of the case
visualise.r
calls plot2this.r
calls ggplot2 and returns p object
Here the fix in the function plot2this.r from return(p) to return(print(p)).
Initial plot2this.r
p <- ggplot(dat.m, aes(x = Vars, y = value, fill=variable))
return(p)
Fix
p <- ggplot(dat.m, aes(x = Vars, y = value, fill=variable))
return(print(p))
Output now: expected output with the wanted plot.

Resources