2

I got a "generator object" from a python function. However, I tried many ways but failed to read the "generator object" in r using reticulate. I know python base function list() can convert "generator object" to "json", which I can then read in r. I wonder how to use base python function in r? (I would not prefer to use py_run_file)

For example:

>library(reticulate)
>foo <- import("foo")
>res <- foo.func()
<generator object at 0x7fd4fe98ee40>
Sunderam Dubey
  • 1
  • 11
  • 20
  • 40
WenliL
  • 419
  • 2
  • 14

2 Answers2

2

You could use iterate or iter_next.

As an example, consider a python generator firstn.py:

def firstn(n):
  num = 0
  while num < n:
    yield num
    num += 1

You can traverse the generator either with iterate :

library(reticulate)
source_python('firstn.py')
gen <- firstn(10)
gen
#<generator object firstn at 0x0000020CE536AF10>

result <- iterate(gen)
result
# [1] 0 1 2 3 4 5 6 7 8 9

or with iter_next:

iter_next(gen)
[1] 0
iter_next(gen)
[1] 1
iter_next(gen)
[1] 2
Waldi
  • 39,242
  • 6
  • 30
  • 78
  • I could use `source_python` to load a function from py, but I prefer not to call another file. I am looking for an alternative python function like `list()/iterate()` but not from base python (so I can just import and run it). Or directly call python `list()/iterate()` in r. – WenliL Feb 09 '22 at 20:22
  • `source_python` was just to create a minimal reproducible example, but did you try `iter_next` on the `res` generator object you got from `import("foo");res <- foo.func()` – Waldi Feb 09 '22 at 20:24
0

I'm not sure if you can in R directly, but you definitely can in R Markdown. I use R Markdown to flip objects back and forth between the two.

I use a basic html_document YAML output. However, I don't typically knit this type of RMD, so I don't think it really matters what you put there if you use it the same way.

When you use reticulate you need an environment.

So first I'll have an R chunk:

```{r setup}

library(tidyverse) # for random r object creation to use in Python
library(reticulate)
use_virtualenv("KerasEnv") # this is an environment I already have setup

# creating R objects to use with Python
str(diamonds)

cut <- diamonds$cut %>% unique()

```

Then I'll create my Python chunk.

```{r usingPy,results="asis",engine="python"}
    
import numpy as np
import random

diamonds_py = r.diamonds # bring dataset into Python

mxX = max(diamonds_py.x) # create a new Python object to bring into R
print(mxX)
# 10.74

cut_py = r.cut # bring vector into Python 

```

Now let's say I want to bring something from Python back into R.

```{r tellMeMore}
# bring Python object into R
mxX_r = py $ mxX
# [1] 10.74 

```

You can run the Python and R code line by line, by chunk, or knit. To clear the Python environment, I'm pretty sure you have to restart RStudio.

Kat
  • 15,669
  • 3
  • 18
  • 51
  • I can use rmarkdown, but py env and r env in rmarkdown are different, which means I need to reproduce the variable using py again. I would prefer to look for a more easy way? – WenliL Feb 09 '22 at 20:20
  • The environment is the same in R and R Markdown without knitting. If it is a matter of knitting, you can copy objects from your environment into your script. I would probably save the objects in an `.Rdata` file; it can house any number of objects. The current directory in terms of RMD when knitting is the folder the RMD is saved in. To save `.Rdata`: `save(obj, obj2, file = "filePath/name.Rdata")` Extract the objects like so `load(file = "filePath/name.Rdata")`. All will load with there original object names. (Don't set this to an object like `newObj = load(...)`.) – Kat Feb 10 '22 at 01:22