1  First steps

Python and R are both popular programming languages used for data analysis and machine learning tasks. While both languages have their own strengths and weaknesses, there are situations where using both languages together can be beneficial.

Using Python and R together can be beneficial when you want to take advantage of the strengths of both languages. Whether you want to use R libraries in Python, Python libraries in R, or combine both languages in a single application, there are many options available for integrating Python and R. Here are some ways in which Python can be used with R:

The reticulate package makes it easy for R users to incorporate Python functionality into their R workflows, whether it’s using Python libraries not available in R, reusing existing Python code, or simply taking advantage of Python’s strengths in specific areas such as machine learning or web development.

First, you need to have Python installed on your system. You can download Python from the official website (https://www.python.org/downloads/) and install it following the instructions provided. Next, install the reticulate package: Open an R session and install the reticulate package by running the following command:

# install reticulate package
install.packages("reticulate")

Once the package is installed, you need to set the Python path in R. The Python path is the location of the Python executable on your system. You can set the path by running the following command:

library(reticulate)
use_python("/Users/edgar/Library/r-miniconda-arm64/envs/r-reticulate/bin/python")

If you’re using the default Python installation on your system, you can skip this step. You can test the installation by running the following command:

py_config()
#> python:         /Users/edgar/Library/r-miniconda-arm64/envs/r-reticulate/bin/python
#> libpython:      /Users/edgar/Library/r-miniconda-arm64/envs/r-reticulate/lib/libpython3.8.dylib
#> pythonhome:     /Users/edgar/Library/r-miniconda-arm64/envs/r-reticulate:/Users/edgar/Library/r-miniconda-arm64/envs/r-reticulate
#> version:        3.8.16 | packaged by conda-forge | (default, Feb  1 2023, 16:01:13)  [Clang 14.0.6 ]
#> numpy:          /Users/edgar/Library/r-miniconda-arm64/envs/r-reticulate/lib/python3.8/site-packages/numpy
#> numpy_version:  1.24.2
#> 
#> NOTE: Python version was forced by use_python() function

This command should display information about your Python installation, including the Python version, the location of the Python executable, and the Python library path. Once the reticulate package is installed and configured, you can start using Python functionality in your R code. For example, you can import Python modules, call Python functions, and access Python objects directly from R.

However, I’ll use a virtual environment for the book and the conda_list() functions returns all (conda) environment of the system.

#List all conda installations
conda_list()
#>             name
#> 1    .PreTrained
#> 2           base
#> 3       EdgarGPT
#> 4      IliartBot
#> 5 IliartGPT.venv
#> 6          flask
#> 7         fuckit
#> 8   r-reticulate
#> 9 streamlit.venv
#>                                                                  python
#> 1         /Users/edgar/Dropbox/Python/PreTrained/.PreTrained/bin/python
#> 2                     /Users/edgar/Library/r-miniconda-arm64/bin/python
#> 3       /Users/edgar/Library/r-miniconda-arm64/envs/EdgarGPT/bin/python
#> 4      /Users/edgar/Library/r-miniconda-arm64/envs/IliartBot/bin/python
#> 5 /Users/edgar/Library/r-miniconda-arm64/envs/IliartGPT.venv/bin/python
#> 6          /Users/edgar/Library/r-miniconda-arm64/envs/flask/bin/python
#> 7         /Users/edgar/Library/r-miniconda-arm64/envs/fuckit/bin/python
#> 8   /Users/edgar/Library/r-miniconda-arm64/envs/r-reticulate/bin/python
#> 9 /Users/edgar/Library/r-miniconda-arm64/envs/streamlit.venv/bin/python

Virtual environments in Python are a useful tool for managing dependencies and ensuring that your project runs smoothly on different systems. Here are several reasons why it is wise to use virtual environments in Python:

Create a Python environment using the virtualenv_create() function. This function creates a new virtual environment and installs the specified packages. For example, to create a virtual environment called “myenv” and install the pandas package, you can run the following command:

virtualenv_create("myenv", packages = "pandas")

Finally, you can install additional Python packages using the py_install() function. This function installs the specified packages in the active Python environment. For example, to install the pandas package, you can run the following command:

py_install("pandas")

The next console achieves the same result with Conda and import the Pandas module.

#install packages
conda_install("r-reticulate", "pandas")
pandas <- import("pandas")

Let us explore some Python packages to see how we can intregrate them in R. For example, Seaborn is a visualization library based on Matplotlib. It provides a high-level interface for creating informative and attractive statistical graphics. It even gives us access to know data sets such as mtcars or Anscombe’s quartet.

Anscombe’s quartet is a set of four datasets that have nearly identical descriptive statistics, yet have very different plots when graphed. The quartet was created by the statistician Francis Anscombe in 1973 to demonstrate the importance of visualizing data and the limitations of summary statistics. Each dataset consists of 11 (x, y) pairs, and the four datasets are designed to have the same mean, variance, correlation, and linear regression line. However, when plotted, each dataset reveals a very different relationship between x and y. The quartet is often used to illustrate the importance of data visualization and exploratory data analysis in understanding and interpreting statistical results.

import seaborn as sns
sns.set_theme(style="ticks")

# Load the example dataset for Anscombe's quartet
df = sns.load_dataset("anscombe")

# Show the results of a linear regression within each dataset
sns.lmplot(
    data=df, x="x", y="y", col="dataset", hue="dataset",
    col_wrap=2, palette="muted", ci=None,
    height=4, scatter_kws={"s": 50, "alpha": 1}
)

Let us load the “mpg” dataset and display the first few rows of the data. If you haven’t already, you’ll need to install Seaborn first (Waskom 2021).

Load Seaborn and the “mpg” dataset: Once you have Seaborn installed, you can load it and the “mpg” dataset using the following Python code. It imports the Seaborn package as “sns” and loads the “mpg” dataset into a variable called “cars”. Moreover, I also import the Pandas package which we will use as well.

#import numpy as np
#import pandas as pd
import seaborn as sns
import pandas as pd

cars = sns.load_dataset("mpg")

To display the first few rows of the “mpg” dataset, you can use the head() function from the Pandas library, which is included in the Seaborn package:

#print(cars)
cars.head()
#>     mpg  cylinders  displacement  ...  model_year  origin                       name
#> 0  18.0          8         307.0  ...          70     usa  chevrolet chevelle malibu
#> 1  15.0          8         350.0  ...          70     usa          buick skylark 320
#> 2  18.0          8         318.0  ...          70     usa         plymouth satellite
#> 3  16.0          8         304.0  ...          70     usa              amc rebel sst
#> 4  17.0          8         302.0  ...          70     usa                ford torino
#> 
#> [5 rows x 9 columns]

The Pandas library is a popular data analysis toolkit for Python. It provides a wide range of functions and tools for working with structured data. For example, the describe() function is used to generate descriptive statistics of a Pandas DataFrame or Series. When called on a DataFrame or Series, the describe() function provides summary statistics such as count, mean, standard deviation, minimum, maximum, and quartiles. The next console shows how to generate descriptive statistics for the “mpg” dataset using the describe() function, you can use the following Python code:

cars.describe()
#>               mpg   cylinders  ...  acceleration  model_year
#> count  398.000000  398.000000  ...    398.000000  398.000000
#> mean    23.514573    5.454774  ...     15.568090   76.010050
#> std      7.815984    1.701004  ...      2.757689    3.697627
#> min      9.000000    3.000000  ...      8.000000   70.000000
#> 25%     17.500000    4.000000  ...     13.825000   73.000000
#> 50%     23.000000    4.000000  ...     15.500000   76.000000
#> 75%     29.000000    8.000000  ...     17.175000   79.000000
#> max     46.600000    8.000000  ...     24.800000   82.000000
#> 
#> [8 rows x 7 columns]

Or consider the mean() function which is used to calculate the arithmetic mean of a Pandas DataFrame or Series. When called on a DataFrame or Series, the mean() function calculates the average value of all the elements in the DataFrame or Series.

cars.mean()
#> mpg               23.514573
#> cylinders          5.454774
#> displacement     193.425879
#> horsepower       104.469388
#> weight          2970.424623
#> acceleration      15.568090
#> model_year        76.010050
#> dtype: float64

Scipy is a popular library for scientific computing in Python, and it provides functions for calculating statistical values, such as the correlation coefficient. Start by importing the necessary packages. You’ll need the scipy.stats module to calculate the correlation coefficient, and you may also need numpy to work with arrays or matrices of data.

import scipy
import scipy.stats as stats
import numpy as np

The scipy.stats module can calculate the correlation coefficient for two arrays, but if you have more than two variables, you’ll need to use a matrix. Use the stats.pearsonr() function to calculate the Pearson correlation coefficient. This function takes two arguments: the two arrays or matrices to compare, and it returns two values: the correlation coefficient and the p-value.

mpg = cars["mpg"]
horsepower = cars["horsepower"]

scipy.stats.pearsonr(mpg, horsepower)
#> ValueError: array must not contain infs or NaNs

Unfortuntely, there is a missing values problem that we need to fix first. In Python, missing values are typically represented by the special value NaN (Not a Number), which is part of the numpy library. There are different ways to drop missing values from a dataset, depending on the context and the desired outcome.

Drop rows or columns with missing values: If you have missing values in your dataset and you want to remove entire rows or columns that contain at least one missing value, you can use the dropna() method. This method removes all rows that contain at least one missing value by default, but you can specify the argument axis=1 to remove columns instead.

If you want to drop missing values only within a specific column, you can use the dropna() method with the subset argument. This argument specifies the column or columns to consider when dropping missing values. The next console shows the first approaches and the results of the correlation coeficient.

cars = cars.dropna()
mpg = cars["mpg"]
horsepower = cars["horsepower"]

scipy.stats.pearsonr(mpg, horsepower)
#> PearsonRResult(statistic=-0.7784267838977761, pvalue=7.031989029403436e-81)

Alternatively, if you have a pandas DataFrame, you can use the pandas.DataFrame.corr() method to calculate the correlation coefficient for all pairs of columns.

corr_matrix = cars.corr(method='pearson')
print(corr_matrix)
#>                    mpg  cylinders  ...  acceleration  model_year
#> mpg           1.000000  -0.777618  ...      0.423329    0.580541
#> cylinders    -0.777618   1.000000  ...     -0.504683   -0.345647
#> displacement -0.805127   0.950823  ...     -0.543800   -0.369855
#> horsepower   -0.778427   0.842983  ...     -0.689196   -0.416361
#> weight       -0.832244   0.897527  ...     -0.416839   -0.309120
#> acceleration  0.423329  -0.504683  ...      1.000000    0.290316
#> model_year    0.580541  -0.345647  ...      0.290316    1.000000
#> 
#> [7 rows x 7 columns]

In the next two chapter we learn more about data preparation, analysis, and visualization with Python. For example, the statsmodels.formula.api module is used to create and fit a linear regression model. The formula for the regression model is defined using a string that specifies the dependent variable and the independent variables, separated by ~ operator which is very similar compared to R. The ols() method is used to create the model, passing in the formula and the dataset. Finally, the fit() method is used to fit the model to the data, and the summary() method is used to print a summary of the model results.

import statsmodels.api as sm
import statsmodels.formula.api as smf

results = smf.ols('mpg ~ horsepower', data=cars).fit()
print(results.summary())
#>                             OLS Regression Results                            
#> ==============================================================================
#> Dep. Variable:                    mpg   R-squared:                       0.606
#> Model:                            OLS   Adj. R-squared:                  0.605
#> Method:                 Least Squares   F-statistic:                     599.7
#> Date:                Tue, 26 Aug 2025   Prob (F-statistic):           7.03e-81
#> Time:                        15:50:14   Log-Likelihood:                -1178.7
#> No. Observations:                 392   AIC:                             2361.
#> Df Residuals:                     390   BIC:                             2369.
#> Df Model:                           1                                         
#> Covariance Type:            nonrobust                                         
#> ==============================================================================
#>                  coef    std err          t      P>|t|      [0.025      0.975]
#> ------------------------------------------------------------------------------
#> Intercept     39.9359      0.717     55.660      0.000      38.525      41.347
#> horsepower    -0.1578      0.006    -24.489      0.000      -0.171      -0.145
#> ==============================================================================
#> Omnibus:                       16.432   Durbin-Watson:                   0.920
#> Prob(Omnibus):                  0.000   Jarque-Bera (JB):               17.305
#> Skew:                           0.492   Prob(JB):                     0.000175
#> Kurtosis:                       3.299   Cond. No.                         322.
#> ==============================================================================
#> 
#> Notes:
#> [1] Standard Errors assume that the covariance matrix of the errors is correctly specified.