DataFrame_R-Pandas-Convert

3182 days ago by takepwave

Hiroshi TAKEMOTO (take@pwv.co.jp)

RとPandas(Sage)でデータフレームの相互変換

これまで、RのグラフをSageで表示したり、RとSage間でのデータの受け渡しを紹介してきましたが、 Rでもっともよく使われるデータフレームについて、まったく考えていませんでした。

しかし、Pandasの機能が強力であり、とても使えるツールであることからRとPandas間のデータフレーム を相互変換することに挑戦してみます。

また、Rのグラフ表示で使っていたRUtil.pyもPNGファイルベースとして高速化をはかり、ここにデータフレーム の相互変換機能を追加することになりました。

新たに追加したデータフレーム変換関数は、以下の2個です。

  • RDf2PandaDf: RのデータフレームをPandasのデータフレームに変換する
  • PandaDf2RDf: PandasのデータフレームをRのデータフレームに変換する

データ変換で使用するパッケージとライブラリ

データフレーム変換で使用するSageのライブラリーは、pandasとnumpyです。 Rは、jsonliteをパッケージを使用します。

# RとPandasのデータフレームを相互に変換する方法 # Sageでは、numpyとpandasをインポート import pandas as pd import numpy as np # Rではjsonliteパッケージを使用 r('library(jsonlite)') # 例としてR Graphic Cookbookのデータを使用 #r("install.packages('gcookbook')") r('library(gcookbook)') 
       
[1] "gcookbook" "jsonlite"  "stats"     "graphics"  "grDevices" "utils" 
"datasets"  "methods"  
[9] "base"     
[1] "gcookbook" "jsonlite"  "stats"     "graphics"  "grDevices" "utils"     "datasets"  "methods"  
[9] "base"     

RからPandasへのデータフレーム変換

RからPandasにデータフレームを変換するために、jsonliteのtoJSONとPandasのread_json関数を使用します。

以下にgcookbookのサンプルデータheightweightをRからPandasのデータフレームに変換する例を示します。

# RからJSON形式でデータを持ってくる方法 # 例として、gcookbookのサンプルデータをRから取得する test_json = r('toJSON(heightweight, pretty=FALSE)') heightweight = pd.read_json(sageobj(test_json)); heightweight.head() 
       
   ageMonth  ageYear  heightIn sex  weightLb
0       143    11.92      56.3   f      85.0
1       155    12.92      62.3   f     105.0
2       153    12.75      63.3   f     108.0
3       161    13.42      59.0   f      92.0
4       191    15.92      62.5   f     112.5

[5 rows x 5 columns]
   ageMonth  ageYear  heightIn sex  weightLb
0       143    11.92      56.3   f      85.0
1       155    12.92      62.3   f     105.0
2       153    12.75      63.3   f     108.0
3       161    13.42      59.0   f      92.0
4       191    15.92      62.5   f     112.5

[5 rows x 5 columns]

関数にまとめる

上記の処理をRDfPandasDfという関数にまとめると以下の様になります。

# これを関数にまとめる # Rのデータフレームをpandasのデータフレームに変換する def RDf2PandaDf(name): json_str = r('toJSON(%s, pretty=FALSE)' % name) return pd.read_json(sageobj(json_str)) 
       

RDf2PandasDfの使用例

RDf2PandasDfを使ってgcookbookのサンプルデータheightweightをRからPandas(Sage) にデータを持ってくる場合の例です。

Rのデータフレーム名をRDf2PandasDfの引数とするとPandasのデータフレームに変換されて返されます。

print RDf2PandaDf('heightweight').head() 
       
   ageMonth  ageYear  heightIn sex  weightLb
0       143    11.92      56.3   f      85.0
1       155    12.92      62.3   f     105.0
2       153    12.75      63.3   f     108.0
3       161    13.42      59.0   f      92.0
4       191    15.92      62.5   f     112.5

[5 rows x 5 columns]
   ageMonth  ageYear  heightIn sex  weightLb
0       143    11.92      56.3   f      85.0
1       155    12.92      62.3   f     105.0
2       153    12.75      63.3   f     108.0
3       161    13.42      59.0   f      92.0
4       191    15.92      62.5   f     112.5

[5 rows x 5 columns]

PandasからRへのデータフレームに変換

今度は、逆にPandasのデータフレームをRのデータフレームに変換します。 いろいろ試したのですが、writeJSONを使った変換では上手く処理できず、 もっともオーソドックスなカラム名とデータフレームのvaluesをzipとdictを 使って辞書の配列に変換する方式に行き着きました。

# 同様に関数にまとめる # pandasのデータフレームをRに渡す def PandaDf2RDf(df, name): l = [dict(zip(df.columns, x)) for x in df.values.tolist()] json_str = str(l) json_str = json_str.replace("'", '\\"') r('%s <- fromJSON("%s")' % (name, json_str)) 
       

PandaDf2RDfの使用例

年齢と性別のデータフレームをPandasで作成し、それをPandaDf2RDfを使って Rのデータフレームに変換します。

# PandasのデータをRに渡す age = [20, 22, 25, 27, 21, 23, 37, 31, 61, 45, 41, 32] sex = ['F', 'M', 'M', 'M', 'F', 'M', 'F', 'M', 'F', 'M', 'F', 'M'] df = pd.DataFrame({'age': age, 'sex': sex}); df.head() 
       
  age sex
0  20   F
1  22   M
2  25   M
3  27   M
4  21   F

[5 rows x 2 columns]
  age sex
0  20   F
1  22   M
2  25   M
3  27   M
4  21   F

[5 rows x 2 columns]

PandaDf2RDfの引数は、変換するデータフレームとRでのデータフレーム変数名です。

以下の例では、上記で作成したdfをRのデータフレームに変換し、aという変数にセットし、 それをSageのr関数を使って表示しています。きちんと変換できているのが確認できます。

PandaDf2RDf(df, "a") r('a') 
       
   age sex
1   20   F
2   22   M
3   25   M
4   27   M
5   21   F
6   23   M
7   37   F
8   31   M
9   61   F
10  45   M
11  41   F
12  32   M
   age sex
1   20   F
2   22   M
3   25   M
4   27   M
5   21   F
6   23   M
7   37   F
8   31   M
9   61   F
10  45   M
11  41   F
12  32   M