# What `R` you? (R vectors in python)

`reticulate`

allows us to toggle between `R`

and `python`

in the same session, callling `R`

objects when running `python`

scripts and vice versa. When calling `R`

data structures in `python`

, the `R`

structures are converted to the equivalent `python`

structures where applicable. However, like translating English to Mandarin, translating `R`

structures to `python`

may not be straightforward which we will see later.

There are 5 `R`

data structures:

vector (more specifically atomic vector)

list

array

matrix (special kind of array which is 2 dimensional)

data frame

In this post, we will look at translating `R`

’s vector into `python`

.

```
# load libraries
library(tidyverse)
library(reticulate)
```

# A `R`

vector is a python …

well it depends if the `R`

vector has single or multiple elements.

## Single element `R`

vector

If the `R`

vector has only 1 element, the python structure will be a scalar. A scalar is a structure which contains a single value. The value can be any type e.g. 69, 0.07, or ‘banana’.

Let’s verify with some code. Is `Rvec_1`

a vector?

```
Rvec_1<-1
is.vector(Rvec_1)
```

`## [1] TRUE`

Indirectly, you can print the `class()`

of the object. If it prints the element type, you can infer the object is a vector.

`class(Rvec_1)`

`## [1] "numeric"`

Is a single element `R`

vector a `python`

scalar structure?

```
py_run_string("import numpy as np")
py_eval("np.isscalar(r.Rvec_1)")
```

`## [1] TRUE`

Likewise, you can print the `type`

of the object. If it prints the element type, you can infer the structure is a scalar.

`py_eval("type(r.Rvec_1)")`

`## <class 'float'>`

If you wish to run everything in `R`

and achieve the above, you will have to convert the `R`

object into a `python`

object and store this converted object in your `R`

’s global environment. From my previous introduction to the `reticulate`

package, you can do this using the`r_to_py`

function.

`r_to_py(Rvec_1) %>% class()`

`## [1] "python.builtin.float" "python.builtin.object"`

There you have it. When you convert a single element `R`

vector into `python`

, it is a `float`

element type which is indicative that it is a `python`

scalar structure.

## Multi element `R`

vector

If the `R`

vector has multiple elements, the python structure will be a list. Let’s assert this with some code. Is `Rvec_multi`

a `R`

atomic vector? The `class()`

is an element type thus it can be inferred to be a `R`

vector.

```
Rvec_multi<-c(66,99, 0.07)
class(Rvec_multi)
```

`## [1] "numeric"`

Is a multi element `R`

vector a `python`

list? Yes, it is.

`r_to_py(Rvec_multi) %>% class()`

`## [1] "python.builtin.list" "python.builtin.object"`

## Named vectors

Occasionally, you may work with named vectors in `R`

; for instance, when calculating quantiles.

`(Rvec_name<-quantile(rnorm(100)))`

```
## 0% 25% 50% 75% 100%
## -2.1896617 -0.8763797 -0.2375871 0.4623371 2.7550884
```

Named vectors are still considered vectors.

`Rvec_name %>% class()`

`## [1] "numeric"`

Do note that the names in the named vectors (e.g. 0%, 25%..) are treated as character and NOT numbers.

`Rvec_name %>% str()`

```
## Named num [1:5] -2.19 -0.876 -0.238 0.462 2.755
## - attr(*, "names")= chr [1:5] "0%" "25%" "50%" "75%" ...
```

However, `python`

ignores the names when translating a multi element named vector. `python`

treats it like another `python`

list.

`r_to_py(Rvec_name)`

`## [-2.189661746762837, -0.8763796933162846, -0.23758708410549662, 0.4623370994806194, 2.7550883808673072]`

# Some differences between `python`

and `R`

## Element types

We have been using element types to infer if the object is a `R`

vector or a `python`

scalar. Thus, it would helpful to know some of the differences between `R`

and `python`

element types.

### Element types (numbers)

By default, `R`

treats numbers as floats/numerics regardless if they are whole numbers or numbers with decimals

`class(1)`

`## [1] "numeric"`

`class(0.07)`

`## [1] "numeric"`

On the other hand, `python`

treats whole numbers as integers.

`py_eval("type(1)")`

`## <class 'int'>`

`Python`

treats number with decimals just like `R`

, as floats/numerics

`py_eval("type(0.07)")`

`## <class 'float'>`

The trick for `R`

to treat whole numbers as integers in the eyes of both `R`

and `python`

is to add the suffix `L`

after the number.

```
Rvec_1int<-1L
class(Rvec_1int)
```

`## [1] "integer"`

`r_to_py(Rvec_1int) %>% class()`

`## [1] "python.builtin.int" "python.builtin.object"`

### Element types(coercing)

Elements in multi element `R`

vectors adhere to singularity. In other words, different element types are coerced such that all elements have the same type.

Let’s look at an example. First, I will create 3 single element vectors of different element types.

```
Relement_int=2L
class(Relement_int)
```

`## [1] "integer"`

```
Relement_bool=TRUE
class(Relement_bool)
```

`## [1] "logical"`

```
Relement_char="banana"
class(Relement_char)
```

`## [1] "character"`

Next, I will combine these vectors into a multi element vector. Let’s reassess the element type for each element.

```
Rvec_mix<- c(Relement_int, Relement_bool, Relement_char)
class(Rvec_mix[1])
```

`## [1] "character"`

`class(Rvec_mix[2])`

`## [1] "character"`

`class(Rvec_mix[3])`

`## [1] "character"`

As you can see, all the different elements have been coerced into the same element type when they are combined in a multi element vector. Often, the individual elements are coerced into strings as strings is the most accommodating element type.

In contrast, `python`

doesn’t coerce element types when lists are created. The integrity of each element type remains unchanged.

```
py_run_string("Plist_mix=(r.Relement_int, r.Relement_bool, r.Relement_char)")
py_eval("type(Plist_mix[0])")
```

`## <class 'int'>`

`py_eval("type(Plist_mix[1])")`

`## <class 'bool'>`

`py_eval("type(Plist_mix[2])")`

`## <class 'str'>`

## Indexing

Besides the differences in element types, there are differences in indexing for each language.

### Indexing (zero/non-zero)

`R`

uses non-zero indexing

`Rvec_multi[1]`

`## [1] 66`

`python`

uses zero indexing

`py_eval("r.Rvec_multi[0]")`

`## [1] 66`

## Indexing (negative numbers)

In addition to non-zero and zero indexing, there are other differences in indexing. In `R`

, negative index number means that the element of that index number is excluded.

`Rvec_multi[-1]`

`## [1] 99.00 0.07`

In `python`

, negative index number means that indexing begins from the end of the dataset.

`py_eval("r.Rvec_multi[-1]")`

`## [1] 0.07`