Embed R code in python - python

I need to make computations in a python program, and I would prefer to make some of them in R. Is it possible to embed R code in python ?

You should take a look at rpy (link to documentation here).
This allows you to do:
from rpy import *
And then you can use the object called r to do computations just like you would do in R.
Here is an example extracted from the doc:
>>> from rpy import *
>>>
>>> degrees = 4
>>> grid = r.seq(0, 10, length=100)
>>> values = [r.dchisq(x, degrees) for x in grid]
>>> r.par(ann=0)
>>> r.plot(grid, values, type=’lines’)

RPy is your friend for this type of thing.
The scipy, numpy and matplotlib packages all do simular things to R and are very complete, but if you want to mix the languages RPy is the way to go!
from rpy2.robjects import *
def main():
degrees = 4
grid = r.seq(0, 10, length=100)
values = [r.dchisq(x, degrees) for x in grid]
r.par(ann=0)
r.plot(grid, values, type='l')
if __name__ == '__main__':
main()

When I need to do R calculations, I usually write R scripts, and run them from Python using the subprocess module. The reason I chose to do this was because the version of R I had installed (2.16 I think) wasn't compatible with RPy at the time (which wanted 2.14).
So if you already have your R installation "just the way you want it", this may be a better option.

Using rpy2.objects. (Tried and ran some sample R programs)
from rpy2.robjects import r
print(r('''
# Create a vector.
apple <- c('red','green',"yellow")
print(apple)
# Get the class of the vector.
print(class(apple))
##########################
# Create the data for the chart.
v <- c(7,12,28,3,41)
# Give the chart file a name.
png(file = "line_chart.jpg")
# Plot the bar chart.
plot(v,type = "o")
# Save the file.
dev.off()
##########################
# Give the chart file a name.
png(file = "scatterplot_matrices.png")
# Plot the matrices between 4 variables giving 12 plots.
# One variable with 3 others and total 4 variables.
pairs(~wt+mpg+disp+cyl,data = mtcars,
main = "Scatterplot Matrix")
# Save the file.
dev.off()
install.packages("plotly") # Please select a CRAN mirror for use in this session
library(plotly) # to load "plotly"
'''))

Related

How can I convert an R multi-element vector to Python list in R Markdown?

I have to read some vector created in an R chunk in a Python chunk in an R Markdown document.
I successfully created the vector, but when I try to attribute the R vector to a Python variable via py_list = r.vector it just doesn't work.
Here there is a peace of the code:
{python ingestao_parcela, eval = py_eval, include = FALSE}
###### IMPORT FEATURE ######
name_layer_tmp = 'parcela_tmp'
arcpy.FeatureClassToFeatureClass_conversion('C:/Users/CLEITE/AppData/Roaming/ESRI/Desktop10.7/ArcCatalog/Connection to BRP01.sde/SDE_GEO.VANT_PARCELA', arcpy.env.workspace, name_layer_tmp, """ DT_MES_REF = {} """.format(dt_mes_ref))
##### CREATE UNIQUE CODE COLUMN #####
arcpy.AddField_management(name_layer_tmp, 'CONCAT_T', 'TEXT')
arcpy.CalculateField_management(name_layer_tmp, 'CONCAT_T',
""" [ESTADO_FEDERATIVO] & "_" & [CD_HORTO] & "_" & [CD_TALHAO] """, 'VB')
##### R VECTOR TO PYTHON LIST #####
dado_amostral_py = r.dado_amostral
dado_amostral_py = tuple(dado_amostral_py)
##### FEATURE FILTER #####
arcpy.FeatureClassToFeatureClass_conversion('parcela_tmp', arcpy.env.workspace,
'parcela', """ [CONCAT_T] IN {} """.format(dado_amostral_py))
PS: I already checked if the R vector "dado_amostral" was created in R indeed, and it was.
I already checked the reticulate CRAN page and I found something about element types conversion.
What I understand from this article is that if I want to use some object created in R inside a Python chunk I only would have to do like I wrote in the beginning: py_list = r.vector.
But when I try to run the R Markdown document, it says that there is no variable such "dado amostral".
Am I missing something?
I've just figured out how to do what I wanted.
The solution I found is:
{r}
r_to_py(dado_amostral)
{python}
py_dado_amostral = r.dado_amostral

Python function as an argument for a R function using rpy2

I wrote a function in Python 2.7:
# Python #
def function_py(par):
#something happens
return(value)
and I want to use this function as an argument for another function in R. More precisely, I want to perform to compute the Sobol' indices using the following function:
# R #
library('sensitivity')
sobol(function_py_translated, X1,X2)
where function_py_translated would b the R equivalent of function_py.
I'm trying to use the rpy2 module, and for a simple function, I could make a working case:
import rpy2.rinterface as ri
import rpy2.robjects.numpy2ri
sensitivity = importr('sensitivity')
radd = ri.baseenv.get('+')
def costfun(X):
a = X[0]
b = X[1]
return(radd(a,b))
costfunr=ri.rternalize(costfun)
X1 = robjects.r('data.frame(matrix(rnorm(2*1000), nrow = 1000))')
X2 = robjects.r('data.frame(matrix(rnorm(2*1000), nrow = 1000))')
sobinde = sensitivity.sobol(costfunr,X1,X2)
print(sobinde.__getitem__(11))
The main problem is that I had to redefine the "+". Is there a way to work around this ? Being able to pass an arbitrary function without prior transformation ? The function I want to analyze is much more complicated.
Thank you very much for your time

Using subset from arules package in rpy2

It's easy to use apriori algorithm from package arules as:
import rpy2.interactive as r
arules = r.packages.importr("arules")
from rpy2.robjects.vectors import ListVector
od = OrderedDict()
od["supp"] = 0.0005
od["conf"] = 0.7
od["target"] = 'rules'
result = ListVector(od)
my_rules = arules.apriori(dataset, parameter=result)
However, apriori subset uses a different format in subset param:
rules.sub <- subset(rules, subset = rhs %in% "marital-status=Never-married" & lift > 2)
It's possible to use this subset function with rpy2?
If subset is (re)defined in the R package arules, the object arules obtained from importr will contain it. In your python code this will look like arules.subset.
The parameter subset is a slightly different story because it is an R expression. There can be several ways to tackle this. One of them is to wrap it in an ad-hoc R function.
from rpy2.robjects import r
def mysubset(rules, subset_str):
return r("function(rules) { arules::subset(rules, subset = %s) }" % \
subset_str)
rules_sub = mysubset(rules,
"rhs %in% "marital-status=Never-married" & lift > 2)

Have phase not equal 0 after 2 pi

if I have a list of phases for a sinusoidal data points and want to make a plot of time vs phase, the plot goes back to 0 after the data is past 2 pi. Is there a way I could manipulate the data so it continues after 2 pi?
I'm currently using phase = [i % 2*np.pi for i in phase], but this doesn't work.
This being about phase isn't important though. Lets say I had a list of data:
data = [0,1,2,0,1,2,0,1,2]
But I didn't want the data to reset to 0 after 2, so I want the data to be:
data = [0,1,2,3,4,5,6,7,8,9]
There are a few ways.
If you use numpy, the de-facto standard math and array manipulation library for python, then just use numpy.unwrap.
If you want to do it yourself or for some reason not use numpy you can do this
def my_unwrap(phase):
phase_diffs = [phase[i+1] - phase[i] for i in range(len(phases)-1)]
unwrapped_phases = [phase[0]]
previous_phase = phase[0]
for phase_diff in phase_diffs:
if abs(phase_diff) > pi:
phase_diff += 2*pi
previous_phase += phase_diff
unwrapped_phases.append(previous_phase)
return unwrapped
Seems to work in basic test cases.

How to construct graphs in Metis for Python

I am using Metis for Python, a Python wrapper for Metis (a graphs partitioning software). I have everything installed and it seems to work correctly, however I do not understand how can I construct a graph to input.
There is an online example in: http://metis.readthedocs.org/en/latest/#example
>>> import networkx as nx
>>> import metis
>>> G = metis.example_networkx()
>>> (edgecuts, parts) = metis.part_graph(G, 3)
>>> colors = ['red','blue','green']
>>> for i, p in enumerate(parts):
... G.node[i]['color'] = colors[p]
...
>>> nx.write_dot(G, 'example.dot') # Requires pydot or pygraphviz
I ran this example and it works fine. However in this example they never specify how to construct the graph “example_networkx()”.
I have tried to construct graphs by networkx : http://metis.readthedocs.org/en/latest/#metis.networkx_to_metis
my code is:
>>> A=nx.Graph()
>>> A.add_edges_from([(3,1),(2,3),(1,2),(3,4),(4,5),(5,6),(5,7),(7,6),(4,10),(10,8),(10,9),(8,9)])
>>> G = metis.networkx_to_metis(A)
>>> (edgecuts, parts) = metis.part_graph(G, 3)
I get an error in the last line. The error is traced back to these lines in the Metis built-in code:
in part_graph(graph, nparts, tpwgts, ubvec, recursive, **opts)
graph = adjlist_to_metis(graph, nodew, nodesz)
in adjlist_to_metis(adjlist, nodew, nodesz)
m2 = sum(map(len, adjlist))
TypeError: object of type 'c_long' has no len()
I have also tried to construct graphs by adjacency list: http://metis.readthedocs.org/en/latest/#metis.adjlist_to_metis
but this gives the same error as before.
I was wondering if anyone has had this problem, or has any idea what I'm doing wrong.
I'm using python 2.7 on Centos 6.5
The metis.part_graph accepts both networkx and adjacency list representation of graphs.
you were almost right when you constructed a networkx graph. However, you should directly pass this graph to part_graph function rather than first converting it to a metis object since part_graph function does not directly accept a metis type graph.
Given an adjajancy matrix A in numpy, an example can be:
# since weights should all be integers
G = networkx.from_numpy_matrix(np.int32(A))
# otherwise metis will not recognize you have a weighted graph
G.graph['edge_weight_attr']='weight'
[cost, parts] = metis.part_graph(G, nparts=30, recursive=True)

Categories

Resources