La guerra entre R y Python es un debate estéril. En la práctica, muchos equipos usan los dos: R para estadística clásica, modelos lineales y visualización; Python para deep learning, APIs y producción. El paquete reticulate hace que ambos lenguajes puedan ejecutarse en la misma sesión, compartiendo objetos sin necesidad de exportar e importar archivos.
reticulate incrusta un intérprete Python dentro de R. Puedes importar cualquier módulo Python, llamar funciones Python desde código R, pasar objetos de un lenguaje al otro y mezclar bloques de código en el mismo script o documento Quarto.
Instalación y configuración
install.packages("reticulate")
library(reticulate)
# Ver qué instalaciones de Python detecta reticulate
py_discover_config()
# Especificar una instalación concreta
use_python("/usr/bin/python3")
use_virtualenv("mi_entorno") # entorno virtual
use_condaenv("base", required = TRUE) # entorno conda
# Crear y usar un entorno virtual gestionado por reticulate
virtualenv_create("r-reticulate")
use_virtualenv("r-reticulate", required = TRUE)
# Instalar paquetes Python desde R
py_install(c("numpy", "pandas", "scikit-learn", "matplotlib"),
envname = "r-reticulate")
# Verificar configuración activa
py_config()
Importar módulos y llamar funciones Python
library(reticulate)
# Importar módulos Python
np <- import("numpy")
pd <- import("pandas")
plt <- import("matplotlib.pyplot")
# Usar numpy desde R
arr <- np$array(c(1.0, 2.0, 3.0, 4.0, 5.0))
np$mean(arr) # 3.0
np$sqrt(arr) # raíz cuadrada de cada elemento
np$random$seed(42L)
mat <- np$random$randn(4L, 4L) # nota: enteros con L para Python int
print(mat)
# Crear DataFrame de pandas desde R
df_r <- data.frame(
nombre = c("Ana", "Luis", "Marta"),
edad = c(28L, 35L, 31L),
score = c(85.5, 72.3, 91.8)
)
# Convertir a pandas DataFrame
df_py <- r_to_py(df_r)
class(df_py) # pandas.core.frame.DataFrame
df_py$describe()
df_py$sort_values("score", ascending = FALSE)
Ejecutar código Python con py_run_string() y bloques py
# Ejecutar código Python como string
py_run_string("
import numpy as np
import pandas as pd
datos = pd.DataFrame({
'x': np.random.randn(100),
'y': np.random.randn(100) * 2 + 1
})
correlacion = datos.corr()
print(correlacion)
")
# Acceder a variables Python creadas en py_run_string
py$datos # el DataFrame de pandas, accesible desde R
py$correlacion # la matriz de correlación
En documentos Quarto o R Markdown puedes alternar bloques ```{r} y ```{python}, y las variables son accesibles entre ellos a través de los objetos r (en Python) y py (en R):
# En un chunk R datos_r <- data.frame(x = 1:10, y = rnorm(10)) # En el siguiente chunk Python (en el mismo documento) # import pandas as pd # df = r.datos_r # accede al data.frame R como pandas DataFrame # print(df.describe()) # De vuelta en R: acceder al objeto Python # py$df # el DataFrame pandas, convertido automáticamente a tibble
Usar scikit-learn desde R
# Entrenar un modelo scikit-learn desde R
sklearn <- import("sklearn")
preprocessing <- import("sklearn.preprocessing")
linear_model <- import("sklearn.linear_model")
model_sel <- import("sklearn.model_selection")
metrics <- import("sklearn.metrics")
# Datos de R convertidos a numpy
set.seed(42)
X <- as.matrix(data.frame(x1 = rnorm(200), x2 = rnorm(200)))
y <- as.integer(X[, 1] + X[, 2] > 0)
# Dividir en train/test
split <- model_sel$train_test_split(X, y, test_size = 0.25,
random_state = 42L)
X_train <- split[[1]]
X_test <- split[[2]]
y_train <- split[[3]]
y_test <- split[[4]]
# Escalar
scaler <- preprocessing$StandardScaler()
X_train <- scaler$fit_transform(X_train)
X_test <- scaler$transform(X_test)
# Ajustar regresión logística de sklearn
clf <- linear_model$LogisticRegression()
clf$fit(X_train, y_train)
y_pred <- clf$predict(X_test)
# Evaluar con métricas de sklearn
cat("Accuracy:", metrics$accuracy_score(y_test, y_pred), "n")
print(metrics$classification_report(y_test, y_pred))
Conversión automática de tipos
reticulate convierte automáticamente los tipos más comunes:
R | Python |
vector numérico | numpy array |
data.frame / tibble | pandas DataFrame |
list | dict o list |
NULL | None |
TRUE / FALSE | True / False |
integer (con L) | int |
Una cosa a tener en cuenta: los enteros R son double por defecto. Para que Python los reciba como int hay que usar el sufijo L: 42L en lugar de 42. Es el error más frecuente al llamar funciones Python que esperan enteros.
Si te interesa la interoperabilidad entre lenguajes en la otra dirección, el artículo sobre Julia con interoperabilidad Python/R/C muestra cómo Julia puede llamar tanto a R como a Python. Y para ver las capacidades estadísticas nativas de R que complementan lo que traes de Python, el artículo sobre modelos estadísticos con lm() y glm() es la referencia.
Imagen: Pexels / Christina Morillo
