Python vs. R: Magia de azúcar sintáctica

Publicado: 2022-07-22

Mi paladar de desarrollo se ha expandido desde que aprendí a apreciar la dulzura que se encuentra en Python y R. La ciencia de datos es un arte que se puede abordar desde múltiples ángulos, pero requiere un equilibrio cuidadoso de lenguaje, bibliotecas y experiencia. Las capacidades expansivas de Python y R brindan azúcar sintáctica: una sintaxis que facilita nuestro trabajo y nos permite abordar problemas complejos con soluciones breves y elegantes.

Estos lenguajes nos brindan formas únicas de explorar nuestro espacio de soluciones. Cada idioma tiene sus propias fortalezas y debilidades. El truco para usar cada una de ellas de manera efectiva es reconocer qué tipos de problemas se benefician de cada herramienta y decidir cómo queremos comunicar nuestros hallazgos. El azúcar sintáctico en cada idioma nos permite trabajar de manera más eficiente.

R y Python funcionan como interfaces interactivas sobre el código de nivel inferior, lo que permite a los científicos de datos usar el lenguaje elegido para la exploración, visualización y modelado de datos. Esta interactividad nos permite evitar el ciclo incesante de editar y compilar código, lo que complica innecesariamente nuestro trabajo.

Estos lenguajes de alto nivel nos permiten trabajar con una fricción mínima y hacer más con menos código. El azúcar sintáctico de cada idioma nos permite probar rápidamente nuestras ideas en un REPL (bucle de lectura-evaluación-impresión), una interfaz interactiva donde el código se puede ejecutar en tiempo real. Este enfoque iterativo es un componente clave en el ciclo moderno de procesamiento de datos.

R vs. Python: expresivo y especializado

El poder de R y Python radica en su expresividad y flexibilidad. Cada idioma tiene casos de uso específicos en los que es más poderoso que el otro. Además, cada lenguaje resuelve problemas a lo largo de diferentes vectores y con muy diferentes tipos de salida. Estos estilos tienden a tener diferentes comunidades de desarrolladores donde se prefiere un idioma. A medida que cada comunidad crece de forma orgánica, su idioma preferido y sus conjuntos de características tienden hacia estilos de azúcar sintáctico únicos que reducen el volumen de código necesario para resolver problemas. Y a medida que la comunidad y el idioma maduran, el azúcar sintáctico del idioma a menudo se vuelve aún más dulce.

Aunque cada idioma ofrece un poderoso conjunto de herramientas para resolver problemas de datos, debemos abordar esos problemas de manera que exploten las fortalezas particulares de las herramientas. R nació como un lenguaje de computación estadística y tiene un amplio conjunto de herramientas disponibles para realizar análisis estadísticos y explicar los datos. Python y sus enfoques de aprendizaje automático resuelven problemas similares, pero solo aquellos que encajan en un modelo de aprendizaje automático. Piense en la computación estadística y el aprendizaje automático como dos escuelas para el modelado de datos: aunque estas escuelas están muy interconectadas, sus orígenes y paradigmas para el modelado de datos son diferentes.

R ama las estadísticas

R se ha convertido en una rica oferta de paquetes para análisis estadístico, modelado lineal y visualización. Debido a que estos paquetes han sido parte del ecosistema R durante décadas, son maduros, eficientes y están bien documentados. Cuando un problema requiere un enfoque de computación estadística, R es la herramienta adecuada para el trabajo.

Las principales razones por las que R es amado por su comunidad se reducen a:

  • Métodos discretos de manipulación, cálculo y filtrado de datos.
  • Operadores de encadenamiento flexibles para conectar esos métodos.
  • Un azúcar sintáctico sucinto que permite a los desarrolladores resolver problemas complejos utilizando cómodos métodos estadísticos y de visualización.

Un modelo lineal simple con R

Para ver cuán sucinto puede ser R, creemos un ejemplo que prediga los precios de los diamantes. Primero, necesitamos datos. Usaremos el conjunto de datos predeterminado de diamonds , que se instala con R y contiene atributos como el color y el corte.

También demostraremos el operador de canalización de R ( %>% ), el equivalente del operador de canalización de línea de comandos de Unix ( | ). Esta pieza popular de la función de azúcar sintáctica de R está disponible en el conjunto de paquetes tidyverse. Este operador y el estilo de código resultante cambia las reglas del juego en R porque permite el encadenamiento de verbos R (es decir, funciones R) para dividir y conquistar una variedad de problemas.

El siguiente código carga las bibliotecas requeridas, procesa nuestros datos y genera un modelo lineal:

 library(tidyverse) library(ggplot2) mode <- function(data) { freq <- unique(data) freq[which.max(tabulate(match(data, freq)))] } data <- diamonds %>% mutate(across(where(is.numeric), ~ replace_na(., median(., na.rm = TRUE)))) %>% mutate(across(where(is.numeric), scale)) %>% mutate(across(where(negate(is.numeric)), ~ replace_na(.x, mode(.x)))) model <- lm(price~., data=data) model <- step(model) summary(model)
 Call: lm(formula = price ~ carat + cut + color + clarity + depth + table + x + z, data = data) Residuals: Min 1Q Median 3Q Max -5.3588 -0.1485 -0.0460 0.0943 2.6806 Coefficients: Estimate Std. Error t value Pr(>|t|) (Intercept) -0.140019 0.002461 -56.892 < 2e-16 *** carat 1.337607 0.005775 231.630 < 2e-16 *** cut.L 0.146537 0.005634 26.010 < 2e-16 *** cut.Q -0.075753 0.004508 -16.805 < 2e-16 *** cut.C 0.037210 0.003876 9.601 < 2e-16 *** cut^4 -0.005168 0.003101 -1.667 0.09559 . color.L -0.489337 0.004347 -112.572 < 2e-16 *** color.Q -0.168463 0.003955 -42.599 < 2e-16 *** color.C -0.041429 0.003691 -11.224 < 2e-16 *** color^4 0.009574 0.003391 2.824 0.00475 ** color^5 -0.024008 0.003202 -7.497 6.64e-14 *** color^6 -0.012145 0.002911 -4.172 3.02e-05 *** clarity.L 1.027115 0.007584 135.431 < 2e-16 *** clarity.Q -0.482557 0.007075 -68.205 < 2e-16 *** clarity.C 0.246230 0.006054 40.676 < 2e-16 *** clarity^4 -0.091485 0.004834 -18.926 < 2e-16 *** clarity^5 0.058563 0.003948 14.833 < 2e-16 *** clarity^6 0.001722 0.003438 0.501 0.61640 clarity^7 0.022716 0.003034 7.487 7.13e-14 *** depth -0.022984 0.001622 -14.168 < 2e-16 *** table -0.014843 0.001631 -9.103 < 2e-16 *** x -0.281282 0.008097 -34.740 < 2e-16 *** z -0.008478 0.005872 -1.444 0.14880 --- Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1 Residual standard error: 0.2833 on 53917 degrees of freedom Multiple R-squared: 0.9198, Adjusted R-squared: 0.9198 F-statistic: 2.81e+04 on 22 and 53917 DF, p-value: < 2.2e-16

R hace que esta ecuación lineal sea simple de programar y comprender con su azúcar sintáctico. Ahora, dirijamos nuestra atención a donde Python es el rey.

Python es mejor para el aprendizaje automático

Python es un lenguaje poderoso de propósito general, con una de sus principales comunidades de usuarios enfocada en el aprendizaje automático, aprovechando bibliotecas populares como scikit-learn, desequilibrio-learn y Optuna. Muchos de los conjuntos de herramientas de aprendizaje automático más influyentes, como TensorFlow, PyTorch y Jax, están escritos principalmente para Python.

El azúcar sintáctico de Python es la magia que adoran los expertos en aprendizaje automático, incluida la sintaxis de canalización de datos sucinta, así como el patrón de ajuste, transformación y predicción de scikit-learn:

  1. Transforme los datos para prepararlos para el modelo.
  2. Construir un modelo (implícito o explícito).
  3. Ajuste el modelo.
  4. Prediga nuevos datos (modelo supervisado) o transforme los datos (no supervisado).
    • Para modelos supervisados, calcule una métrica de error para los nuevos puntos de datos.

La biblioteca scikit-learn encapsula la funcionalidad que coincide con este patrón mientras simplifica la programación para la exploración y visualización. También hay muchas funciones correspondientes a cada paso del ciclo de aprendizaje automático, que proporcionan validación cruzada, ajuste de hiperparámetros y canalizaciones.

Un modelo de aprendizaje automático de diamante

Ahora nos centraremos en un ejemplo simple de aprendizaje automático usando Python, que no tiene una comparación directa en R. Usaremos el mismo conjunto de datos y resaltaremos el patrón de ajuste-transformación-predicción en un código muy ajustado.

Siguiendo un enfoque de aprendizaje automático, dividiremos los datos en particiones de entrenamiento y prueba. Aplicaremos las mismas transformaciones en cada partición y encadenaremos las operaciones contenidas con una canalización. Los métodos (ajuste y puntuación) son ejemplos clave de potentes métodos de aprendizaje automático contenidos en scikit-learn:

 import numpy as np import pandas as pd from sklearn.linear_model LinearRegression from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler from sklearn.preprocessing import OneHotEncoder from sklearn.impute import SimpleImputer from sklearn.pipeline import Pipeline from sklearn.compose import ColumnTransformer from pandas.api.types import is_numeric_dtype diamonds = sns.load_dataset('diamonds') diamonds = diamonds.dropna() x_train,x_test,y_train,y_test = train_test_split(diamonds.drop("price", axis=1), diamonds["price"], test_size=0.2, random_state=0) num_idx = x_train.apply(lambda x: is_numeric_dtype(x)).values num_cols = x_train.columns[num_idx].values cat_cols = x_train.columns[~num_idx].values num_pipeline = Pipeline(steps=[("imputer", SimpleImputer(strategy="median")), ("scaler", StandardScaler())]) cat_steps = Pipeline(steps=[("imputer", SimpleImputer(strategy="constant", fill_value="missing")), ("onehot", OneHotEncoder(drop="first", sparse=False))]) # data transformation and model constructor preprocessor = ColumnTransformer(transformers=[("num", num_pipeline, num_cols), ("cat", cat_steps, cat_cols)]) mod = Pipeline(steps=[("preprocessor", preprocessor), ("linear", LinearRegression())]) # .fit() calls .fit_transform() in turn mod.fit(x_train, y_train) # .predict() calls .transform() in turn mod.predict(x_test) print(f"R squared score: {mod.score(x_test, y_test):.3f}")

Podemos ver cuán optimizado es el proceso de aprendizaje automático en Python. Además, las clases de sklearn de Python ayudan a los desarrolladores a evitar fugas y problemas relacionados con el paso de datos a través de nuestro modelo, al mismo tiempo que generan código estructurado y de nivel de producción.

¿Qué más pueden hacer R y Python?

Además de resolver aplicaciones estadísticas y crear modelos de aprendizaje automático, R y Python se destacan en informes, API, tableros interactivos y la inclusión simple de bibliotecas de código externas de bajo nivel.

Los desarrolladores pueden generar informes interactivos tanto en R como en Python, pero es mucho más sencillo desarrollarlos en R. R también admite la exportación de esos informes a PDF y HTML.

Ambos lenguajes permiten a los científicos de datos crear aplicaciones de datos interactivas. R y Python utilizan las bibliotecas Shiny y Streamlit, respectivamente, para crear estas aplicaciones.

Por último, R y Python admiten enlaces externos a código de bajo nivel. Esto generalmente se usa para inyectar operaciones de alto rendimiento en una biblioteca y luego llamar a esas funciones desde el idioma elegido. R usa el paquete Rcpp, mientras que Python usa el paquete pybind11 para lograr esto.

Python y R: cada día más dulces

En mi trabajo como científico de datos, uso tanto R como Python con regularidad. La clave es comprender dónde es más fuerte cada idioma y luego ajustar un problema para que encaje dentro de una solución elegantemente codificada.

Al comunicarse con los clientes, los científicos de datos quieren hacerlo en el idioma que se entienda más fácilmente. Por lo tanto, debemos sopesar si una presentación estadística o de aprendizaje automático es más efectiva y luego usar el lenguaje de programación más adecuado.

Python y R proporcionan cada uno una colección cada vez mayor de azúcar sintáctico, lo que simplifica nuestro trabajo como científicos de datos y facilita su comprensión para otros. Cuanto más refinada sea nuestra sintaxis, más fácil será automatizar e interactuar con nuestros lenguajes preferidos. Me gusta que mi lenguaje de ciencia de datos sea dulce, y las soluciones elegantes que resultan son aún más dulces.

Lecturas adicionales en el blog de ingeniería de Toptal:

  • Una introducción a la teoría del aprendizaje automático y sus aplicaciones: un tutorial visual con ejemplos
  • Patrones de diseño de Python: para un código elegante y de moda
  • Análisis de Redes Sociales en R y Gephi: Profundizando en Twitter
  • Exploración de algoritmos de aprendizaje automático supervisado
  • Garantía de código limpio: una mirada a Python, parametrizado