Языки программирования — это инструменты, и, как и инструменты, ни один отдельный язык программирования не подходит наилучшим образом для каждой проблемы. Конечно, отверткой можно забить гвоздь в стену, но как насчет молотка? Наука о данных, как и проекты по улучшению дома, лучше, когда мы подходим к ней с разнообразным набором инструментов в нашем распоряжении.

В литературе ведутся споры о том, какой язык лучше. R — это абсолютная мощь для статистики, а Python имеет преимущество в том, что он является более универсальным языком. Однако для большинства проблем речь идет не столько о самом языке программирования, сколько о библиотеках и пакетах, доступных для этого конкретного языка.

Пакет R Tidyverse упрощает работу с фреймами данных благодаря своей построчной механике конвейерной обработки. Библиотека Python Pandas обрабатывает фреймы данных, используя более объектно-ориентированный подход. Однако в конечном итоге и Tidyverse, и Pandas (наряду с другими основными библиотеками Python, такими как numpy) могут выполнять довольно схожие функции. Однако не у каждого инструмента есть двойник на разных языках, и даже dplyr и pandas имеют свои отличия.

Что, если вы ввели сотни строк в проект на R и поняли, что вам нужна функция из библиотеки Python для решения вашей последней проблемы? Что, если вам нужно написать анализ на Python, но вы хотите визуализировать его с помощью библиотеки R ggplot2?

Недавно я столкнулся с этой проблемой при настройке проекта сетевого анализа в R, но ни одна из нативных библиотек не сделала то, что мне было нужно, а также библиотека Python NetworkX. К счастью, люди из Posit (ранее RStudio) готовы помочь с пакетом Reticulate.

Сетчатый означает формирование сети или соединений. Пакет Reticulate устанавливает связь между R и Python, что значительно расширяет возможности инструментов для решения проблем, доступных исследователям данных.

Начало работы с Reticulate

Прежде чем мы сможем начать использовать Python в R, нам нужно выполнить некоторые настройки. Во-первых, необходимо установить и R, и Python. Пакет reticulate автоматически использует версию Python в системном PATH, но вы также можете выбрать версию Python вручную. Дополнительные сведения см. на странице Начало работы с Reticulate.

Примечание. Поскольку пакет Reticulate является пакетом R, мы должны перенести Python в R.

Как и все пакеты в R, мы начинаем с комбинации:

# install and load the reticulate package
install.packages("reticulate") # install from CRAN
library(reticulate) # load the reticulate package

Для установки пакетов Python мы используем функцию py_install(). Reticulate автоматически создает среду по умолчанию под названием «r-reticulate», в которую он устанавливает пакеты Python из pip. Например:

py_install("pandas")

Существует функциональность для взаимодействия Reticulate с Conda и Virtualenv. Для получения дополнительной информации см. страницу справки по установке пакета.

Теперь, когда мы загружаем библиотеку Python в R, она работает немного иначе, чем простой вызов функции library(). Вместо этого мы вызываем функцию Reticulate import. Давайте попробуем:

import("pandas") # Reticulate loads pandas from the virtual environment

# Which returns
Module(pandas)

Что происходит с этим объектом Module(pandas)? Когда мы вызываем library(), все функции в пакете загружаются в пространство имен, поэтому у нас есть к ним доступ. Вызов import() делает то же самое, но сохраняет все функции в этом объекте Module(). Итак, как нам получить доступ к реальным функциям Python? Мы создаем переменную для хранения модуля, к которому мы сможем получить доступ позже.

pandas <- import("pandas") # Load Module(pandas) into its own variable

Хорошо, но теперь нам нужно получить доступ к функциям в переменной pandas. Мы будем использовать то же соглашение $, что и в R data.frames. Например, чтобы использовать функцию Pandas read_csv(), мы должны написать:

pandas$read_csv('path/to/file.csv')

Давайте рассмотрим пример и попробуем взять фрейм данных в r и выполнить некоторые функции в pandas в том же скрипте. Мы будем использовать классический набор данных mtcars.

                   mpg cyl disp  hp drat    wt  qsec vs am gear carb
Mazda RX4         21.0   6  160 110 3.90 2.620 16.46  0  1    4    4
Mazda RX4 Wag     21.0   6  160 110 3.90 2.875 17.02  0  1    4    4
Datsun 710        22.8   4  108  93 3.85 2.320 18.61  1  1    4    1
Hornet 4 Drive    21.4   6  258 110 3.08 3.215 19.44  1  0    3    1
Hornet Sportabout 18.7   8  360 175 3.15 3.440 17.02  0  0    3    2
Valiant           18.1   6  225 105 2.76 3.460 20.22  1  0    3    1

Допустим, мы хотим создать сводную таблицу набора данных, которая показывает, как mpg зависит от количества цилиндров (cyl) и передач (gear). Я могу получить данные с помощью dplyr:

library(dplyr)
mtcars %>% 
  group_by(cyl, gear) %>%
  summarize(mean = mean(mpg))
Output
# A tibble: 8 × 3
# Groups:   cyl [3]
    cyl  gear  mean
  <dbl> <dbl> <dbl>
1     4     3  21.5
2     4     4  26.9
3     4     5  28.2
4     6     3  19.8
5     6     4  19.8
6     6     5  19.7
7     8     3  15.0
8     8     5  15.4

Выглядит здорово, но взаимосвязь между тремя переменными не совсем очевидна. Что нам действительно нужно, так это сводная таблица, и библиотека dplyr здесь нам не поможет. Вместо того, чтобы переносить наш анализ на Python, мы можем перенести Python на R!

pandas <- import("pandas")
numpy <- import("numpy") # use py_install("numpy") to install

df <- pandas$pivot_table(
  mtcars,
  values='mpg',
  index='gear',
  columns='cyl',
  aggfunc=numpy$sum # notice the call to the numpy module to use the Python sum function
)
Output
    4.0  6.0   8.0
3  21.5 39.5 180.6
4 215.4 79.0   NaN
5  56.4 19.7  30.8

Исходные скрипты Python в R

Помимо импорта пакетов для использования в R, мы также можем импортировать в R отдельные скрипты! Вместо import() мы используем функцию source_python() для загрузки отдельных скриптов Python в качестве объектов модуля.

source_python('path/to/script.py')

Примечание. Задавать рабочий каталог вручную не рекомендуется. Необходимо использовать общий путь к файлам либо из а) базовой библиотеки системы (C:, Macintosh HD, Onedrive и т. д.), либо б) из каталога проекта (идентифицируйте файлы в каталоге с помощью list.files()).

Интересно, что source_python() загружает функции из данного скрипта в глобальную среду R, а не в модуль. Другими словами, нам не нужно определять переменную для загрузки наших функций Python при использовании пользовательских скриптов.

Скажем, у нас есть файл Python с именем addition.py, который принимает сумму двух значений:

# addition.py
def add(num1, num2):
    numSum = num1 + num2
    return(numSum)

Затем мы можем вызвать наш пользовательский скрипт Python в R. Например, предположим, что скрипт R определяет два числа, а затем вызывает наш скрипт Python для их суммирования. Вот как это выглядит:

first_number <- 100
second_number <- 200

# load custom python script's add function into the global environment
source_python("addition.py") 

# call the add function
add(first_number, second_number)

Reticulate перевел нашу функцию add из Python в функцию R. Та же функциональность работает и для скриптов Python с несколькими функциями.

Великий разрыв между R и Python был устранен не появлением победителя, а возможностью объединить сильные стороны обоих! В пакет Reticulate стоит погрузиться всем, кто только начинает свое путешествие по науке о данных, и тем, кто уже идет по этому пути. Это не что иное, как изменение игры.

Посетите Веб-сайт Reticulate для получения дополнительной информации. Это немного сложно в точках, поэтому не стесняйтесь делиться, если у вас есть какие-либо вопросы по началу работы с пакетом.

Поставьте лайк, подпишитесь и загляните в мой профиль, чтобы узнать о других уроках по программированию и примерах. Я надеюсь выпускать по одной статье в неделю в течение следующих нескольких месяцев. До сих пор я писал в основном о науке о данных и, вероятно, в будущем коснусь некоторых тем, связанных с гражданским строительством.