Совмещение R и Python

Почему, когда и как

Ирина Голощапова
Эксперт Центра макроэкономического анализа и краткосрочного прогнозирования

Почему

Почему

  1. Синергия преимуществ
    Совмещение мощных и стабильных библиотек R и Python
  2. Скорость и удобство
    Комбинация имеющихся навыков программирования на R и Python

Почему

Синергия преимуществ

Комбинация мощных и стабильных библиотек R и Python:

  • Python - язык общего назначения:
    • Web scraping и crawling (beautifulsoup, Scrapy, и т.д.)
    • Работа с базами данных и приложениями (sqlachemy, и т.д.)
    • Реализация классических ML алгоритмов (scikit-learn, pandas, numpy, scipy, и т.д.)
  • R - обширная коллекция библиотек:
    • Продвинутый статистический анализ. В особенности, для ряда специфических областей науки и практики (анализ врем. рядов и многое другое)
    • Интерактивная графика/dashboards/приложения (htmlwidgets, flexdashboard, shiny, slidify, и т.д.)
    • Быстрые и эффективные библиотеки для сложных манипуляций с данными (data.table, big.data.table, dplyr, и т.д.)

Почему

Скорость и удобство

Комбинация имеющихся навыков программирования на R и Python:

  • различный уровень знаний каждого языка у сотрудников в рамках проекта

  • ваш опыт решения конкретных задач на разных языках

  • предпочтения по синтаксису

Когда

Когда

  1. Исследовательский анализ данных
  2. Прототипирование
  3. Проект/набор задач с широким охватом по различным научно-практическим областям
  4. Очень близкий дедлайн короткие сроки на выполнение задачи

Как

Как

  1. Command line tools. Исполнение скриптов с помощью командной строки + промежуточное хранение файлов на диске (filling air gap)

  2. Interfacing R and Python. Одновременный запуск процессов R и Python и передача данных между ними в оперативной памяти (in-memory)

  3. Другие подходы

Как - Command line tools

Исполнение скриптов с помощью командной строки

<cmd_to_run> <path_to_script> <any_additional_args>

Command Python R
Cmd python path/to/myscript.py arg1 arg2 arg3 Rscript path/to/myscript.R arg1 arg2 arg3
Fetch arguments #character vector of args
myArgs <- commandArgs(trailingOnly = TRUE)
#list, 1st el. - file executed
import sys
my_args = sys.argv

Промежуточное хранение файлов

Medium Storage Python R
Flat files ======= =======
csv csv, pandas readr, data.table
json json jsonlite
yaml PyYAML yaml
Databases ======= =======
SQL sqlalchemy, pandasql
pyodbc
sqlite, RODBS,
RMySQL, sqldf, dplyr
NoSQL PyMongo RMongo
Feather ======= =======
for data frames feather feather
Numpy ======= =======
for numpy objects numpy RcppCNPy

bench_feather

Как - Command line tools - Примеры

# max.R
randomvals <- rnorm(75, 5, 0.5)
par(mfrow = c(1, 2))
hist(randomvals, xlab = 'Some random numbers')
plot(randomvals, xlab = 'Some random numbers', ylab = 'value', pch = 3)
# splitstr.py
import sys

# Get the arguments passed in
string = sys.argv[1]
pattern = sys.argv[2]

# Perform the splitting
ans = string.split(pattern)

# Join the resulting list of elements into a single newline
# delimited string and print
print('\n'.join(ans))
# calling R from Python
import subprocess

# Define command and arguments
command = 'Rscript'
path2script = 'path/to your script/max.R'

# Variable number of args in a list
args = ['11', '3', '9', '42']

# Build subprocess command
cmd = [command, path2script] + args

# check_output will run the command and store to result
x = subprocess.check_output(cmd, universal_newlines=True)

print('The maximum of the numbers is:', x)
# calling Python from R
command = "python"

# Note the single + double quotes in the string (needed if paths have spaces)
path2script ='"path/to your script/splitstr.py"'

# Build up args in a vector
string = "3523462---12413415---4577678---7967956---5456439"
pattern = "---"
args = c(string, pattern)

# Add path to script as first arg
allArgs = c(path2script, args)

output = system2(command, args=allArgs, stdout=TRUE)

print(paste("The Substrings are:\n", output))

Как - Command line tools - Pros&Cons

Преимущества

  • Простой метод и поэтому часто наиболее быстрый
  • Просто увидеть промежуточный результат
  • Возможность чтения/записи большинства форматов реализована в обоих языках

Недостатки

  • Конструкция быстро становится громоздкой и сложноуправляемой по мере роста числа переходов между языками
  • Как правило, существенная потеря в скорости записи/чтения файлов при росте объема данных
  • Необходимость заранее согласовывать схему взаимодействия между языками и формат промежуточных файлов

Как - Interfacing R and Python

Внимание!

R из Python

Библиотеки Комментарии
rpy2 - C-level interface
- прямая поддержка pandas
- поддержка графики (+ggplot2)
- слабая поддержка Windows
pyper - Python code
- use of pipes (в среднем быстрее)
- косвенная поддержка pandas
- ограниченная поддержка графики
- плохая документация
pyrserve - Python code
- удаленные вычисления/Rserve
- нет поддержки для таблиц

Python из R

Библиотеки Комментарии
rPython - Java code
- передача данных через json
- непрямая передача таблиц
- хорошая документация
- слабая поддержка Windows
- часто падает с Anaconda
RSPython - двухсторонний интерфейс
- нет поддержки после 2005
- слабая поддержка Windows
Rcpp - через C++ (Boost.Python и Rcpp)
- нужны специфические навыки
- хороший пример

Как - Interfacing R and Python - Примеры

from rpy2.robjects import pandas2ri # loading rpy2
from rpy2.robjects import r
pandas2ri.activate() # activating pandas module
df_iris_py = pandas2ri.ri2py(r['iris']) # from r data frame to pandas
df_iris_r = pandas2ri.py2ri(df_iris_py) # from pandas to r data frame 
plotFunc = r("""
   library(ggplot2)
   function(df){
   p <- ggplot(iris, aes(x = Sepal.Length, y = Petal.Length)) 
          + geom_point(aes(color = Species))
   print(p)
   ggsave('iris_plot.pdf', plot = p, width = 6.5, height = 5.5)
 }
""") # ggplot2 example
gr = importr('grDevices') # necessary to shut the graph off
plotFunc(df_iris_r)
gr.dev_off()
library(rPython)

# data frames transportation
python.assign('iris_py_dict', iris) # r data.frame to python dict
python.exec('import pandas as pd')
# convert dict to pd data frame
python.exec('iris_py_df = pd.DataFrame(iris_py_dict)')
# convert pd df back to dict
python.exec('iris_py_dict = iris_py_df.to_dict(outtype = "list")') 
# dict to r list to data frame
iris_df <- data.frame(python.get('py_dict2')) 

# python get/python_load
python.load("hello_world.py") ## hello_world = 'hello' + 'world' +'!'
greeting <- python.get("hello_world")
print(greeting) # class character

Как - Interfacing R and Python - Pros&Cons

Преимущества

  • Гибкий и интерактивный способ
  • Быстрая взаимная передача объектов в рамках оперативной памяти

Недостатки

  • Необходимость читать туториалы!
  • Тонкости в сопоставимости объектов и способах их передачи между языками
  • Передача больших объемов данных также может быть затруднительной
  • Слабая поддержка Windows ОС
  • Нестабильность между версиями библиотек

Как - Другие подходы

Как - Расширенный пример

Выводы

  • Можно и нужно совмещать R и Python!
    В особенности в целях исследовательского анализа данных и прототипирования
  • Внимательно относитесь к выбору способов совмещения, основываясь на целях проекта:
    • Command line tools: просто, понятно и обязательно будет работать.
      Отличный способ для начала!
      Внимание к формату feather!
    • Interfacing R and Python: быстро, гибко и временами интерактивно.
      Специфический синтаксис - необходимо читать туториалы, более сложная настройка.
      Используйте проверенные и стабильные библиотеки: rpy2 и rPython.
    • Другие подходы. Внимание к проекту Beaker Notebook!

Спасибо за внимание!

Контакты для связи

gmailigoloshchapova@forecast.ru
githubirinagoloshchapova
repoProgs/DataFest2016_R_Py