本文へスキップ
からだにいいもの

Rのトピックスを中心に『まだ、まだ、知らない、役に立つ情報?』を発信します。

Rで解析:RからPythonのモジュールを呼び出して連携する「reticulate」パッケージの紹介

「reticulate」パッケージは、RからPythonのモジュールやコマンドを呼び出し、R側の値とPython側の値を相互に変換するパッケージです。Rを主な作業環境にしながら、Pythonにしか無いライブラリを分析の一部分に取り入れたい場面に向いています。ふだんの処理の一部をPythonへ渡すところから始められるのではないかと考えます。

パッケージバージョンは1.47.0。Windows 11 x64 (build 26200)のR version 4.6.1で確認しています。

パッケージのインストール

下記コマンドを実行してください。

Python本体が見つからない場合はインストールの確認が表示されます。個別のPythonライブラリは、使う直前にpy_require(“ライブラリ名”)で宣言するか、reticulate::py_install(“ライブラリ名”)で導入します。

# パッケージのインストール
install.packages("reticulate")

# パッケージの読み込み
library("reticulate")
スポンサーリンク

コマンド例

詳細はコメント、パッケージのヘルプを確認してください。

RのベクトルやリストをPythonへ渡すときはr_to_py()、Pythonの戻り値をRで受け取るときはpy_to_r()を使用します。結果は数値ベクトルとリスト、名前付きリストと辞書、といった対応で自動的に変換されます。

以降の例では、京都府の宇治茶の主な産地である5つの市町(宇治市・宇治田原町・和束町・南山城村・京田辺市)について、茶の作付面積(ヘクタール)と年間の収穫量(トン)を想定したデータを使用します。

# 宇治茶の産地5市町の作付面積と年間収穫量
ujicha <- data.frame(
  市町 = c("宇治市", "宇治田原町", "和束町", "南山城村", "京田辺市"),
  面積 = c(58, 92, 210, 145, 34),
  収穫量 = c(190, 305, 720, 480, 110),
  stringsAsFactors = FALSE
)

[Pythonモジュールの読み込み]:importコマンド

Pythonのモジュールを読み込み、Rのオブジェクトで返します。オブジェクトの要素を$でたどると、そのモジュール内のコマンドや定数にアクセスできます。次の例ではPython標準ライブラリのstatisticsモジュールを読み込み、収穫量の平均と母標準偏差を求めます。

オプション意味初期値
module読み込むPythonモジュールの名前なし
asモジュール名の別名(生成されるRクラスの名前に影響する)。S3のクラス名を変えてメソッドの振り分けに影響しうるため、通常はパッケージ開発時にのみ使う上級者向けのオプションNULL
convert論理値。PythonオブジェクトをRの相当物へ自動変換するか。FALSEのときも py_to_r() で手動変換できるTRUE
delay_load論理値。モジュールの読み込みを初回使用時まで遅らせるか。FALSEのときは即座に読み込むFALSE
# Python標準ライブラリのstatisticsモジュールを読み込む
stats_py <- import("statistics")

# 5市町の収穫量の平均
stats_py$mean(ujicha$収穫量)
[1] 361

# 5市町の収穫量の母標準偏差
stats_py$pstdev(ujicha$収穫量)
[1] 218.3667

[文字列で書いたPythonコードの実行]:py_run_stringコマンド

文字列として渡したPythonコードを実行します。コマンドやクラスを定義すると、それらはPythonのメインモジュールに置かれ、Rからはpyオブジェクトの要素として呼び出せます。次の例では、収穫量と面積から10アールあたりの収量(キログラム)を計算するコマンドをPython側で定義し、Rから呼び出します。

オプション意味初期値
code実行するPythonコードなし
local論理値。Pythonオブジェクトを局所的な辞書の中に作るか。FALSEのときはメインモジュールの範囲に作るFALSE
convert論理値。PythonオブジェクトをRの相当物へ自動変換するか。FALSEのときも py_to_r() で手動変換できるTRUE
# 収穫量(トン)と面積(ヘクタール)から10アールあたり収量(キログラム)を返すコマンドをPythonで定義する
py_run_string("
def yield_per_10a(harvest_t, area_ha):
    return [round(h * 1000 / (a * 10), 1) for h, a in zip(harvest_t, area_ha)]
")

# 定義したコマンドをRから呼び出す
py$yield_per_10a(ujicha$収穫量, ujicha$面積)
[1] 327.6 331.5 342.9 331.0 323.5

[Python式の評価]:py_evalコマンド

1つのPython式を評価し、その値を返します。文を書くpy_run_string()と違い、こちらは式に限られる代わりに結果を直接受け取れます。次の例では、収穫量の合計を求める式と、市町名のうち「市」で終わるものだけを残すリスト内包表記を評価します。

オプション意味初期値
code単一のPython式なし
convert論理値。PythonオブジェクトをRへ自動変換するかTRUE
# 収穫量の合計を1つのPython式で求める
py_eval("190 + 305 + 720 + 480 + 110")
[1] 1805

# 市町名のうち「市」で終わるものだけを残すリスト内包表記
py_eval("[m for m in ['宇治市', '宇治田原町', '和束町', '京田辺市'] if m.endswith('市')]")
[1] "宇治市"   "京田辺市"

[RオブジェクトのPythonオブジェクトへの変換]:r_to_pyコマンド

RのオブジェクトをPythonのオブジェクトへ変換します。名前付きリストはPythonの辞書に変換されます。自動変換に任せず、Python側のオブジェクトのまま保持して続きの処理へ渡したいときに使います。次の例では、市町ごとの面積をまとめた名前付きリストを辞書へ変換します。

オプション意味初期値
x変換の対象となるRオブジェクトなし
convert論理値。生成したPythonオブジェクトに対する以降の操作で、結果をRの相当物へ自動変換するか。FALSEのときも py_to_r() で手動変換できるFALSE
# 市町ごとの面積(ヘクタール)を名前付きリストにする
area <- list(宇治市 = 58, 和束町 = 210, 南山城村 = 145)

# Pythonの辞書へ変換する
area_py <- r_to_py(area)

# 変換後のオブジェクトのクラス
class(area_py)
[1] "python.builtin.dict"   "python.builtin.object"

# Python側での表示
area_py
{'宇治市': 58.0, '和束町': 210.0, '南山城村': 145.0}

[配列の形状変更]:array_reshapeコマンド

ベクトルや配列を、指定した次元へ並べ替えます。Rのdim()による並べ替えが列優先(最初の添字が先に進む)なのに対し、このコマンドは既定で行優先で読み出すため、NumPyの規則に合わせて配列を組み立てられます。次の例では、3市町×2年分の収穫量を並べた1本のベクターを、3行2列へ並べ替えます。

オプション意味初期値
x並べ替える配列なし
dim配列に設定する新しい次元なし
order並べ替えのときにxの要素を読み出す順序。”C” は行優先で最後の添字が最も速く変化する。”F” は列優先で最初の添字が最も速く変化するc(“C”, “F”)
# 3市町×2年分の収穫量(トン)を1本のベクターで用意する
harvest2y <- c(190, 200, 305, 320, 720, 700)

# 行優先で3行2列へ並べ替える
array_reshape(harvest2y, c(3, 2))
     [,1] [,2]
[1,]  190  200
[2,]  305  320
[3,]  720  700

[NumPy配列の作成]:np_arrayコマンド

Rのベクトルや配列から、NumPyの配列を直接作成します。dtypeでデータ型を、orderでメモリ上の並び順を指定できます。作成した配列は、import(“numpy”)で読み込んだNumPyのコマンドへそのまま渡せます。次の例では、収穫量を倍精度のNumPy配列にして、全体の平均を求めます。

オプション意味初期値
data配列の元にするベクター、または既存のNumPy配列なし
dtypeNumPyのデータ型(”float32″、”float64″ など)NULL
order配列のメモリ上の並び順。”C” はC言語式、”F” はFortran式“C”
# numpyを読み込む
np <- import("numpy")

# 収穫量を倍精度のNumPy配列にする
harvest_np <- np_array(ujicha$収穫量, dtype = "float64")

# 生成した配列
harvest_np
array([190., 305., 720., 480., 110.])

# 配列全体の平均
np$mean(harvest_np)
[1] 361


この記事が誰かの役に立ちますように。

スポンサーリンク
価格および配送状況は変更される場合があります。購入時は商品ページをご確認ください。
当サイトに表示されている商品情報はAmazonから提供されたものであり、更新または削除される場合があります。
karada-goodはAmazonアソシエイトとして、適格販売により収入を得ています。