Help us understand the problem. What is going on with this article?

Python for .NETを使ってPandas DataFrame から System.Data.DataTableへ変換する

Pythonと.NETの表データ交換

そもそもPython -> .NETでデータフレームを交換する場合、.NET側はDataTableという標準ライブラリのクラスがあるので、それが適しています。決してPandasやdplyrのような高機能なデータ処理能力は無いのですが、とりあえずマッピングすることができます。
BayesServerでPythonからも呼びたい場合は、以下にあるようにJPypeを使ったJavaライブラリへのアクセスを推奨されているようです。

Setup Python

一方で、pythonnetでもいいよ、と一言書いてあり、何で.NETネイティブなのに、Javaラッパーを通さないといけないのかよくわからないので、そちらで行くことにしました。RのラッパーもJavaラッパーを通します。これだと、APIリファレンスを2種類見ないといけない羽目になります。(どっちみち.NETライブラリに改造を加えて、再ラップするので)
最初からPythonにしておけば良かった。。。

pythonnet

pythonnet はPython for .NETと呼ばれる、Pythonから.NETのアクセスライブラリです。
http://pythonnet.github.io/
Pythonから.NETを呼び出す場合、.NETからPythonを呼び出す場合の双方で使えますね。

Python + .NETですと、IronPythonを思い出す人もいるのでしょうけども、そちらは.NET上で動くCLI言語です。これだと、データサイエンスなどで定評のあるライブラリも対応は限られます。というかnumpyが動きません。

pythonnetは言語間の接続を行うだけなので、両者の良いところを残したまま使えます。最新の.NET Coreなどにも対応します。
感覚的に言うと、

  • Pythonから、.NETのライブラリを using ではなく importで使える。
import clr
clr.AddReference("System.Windows.Forms")
from System.Windows.Forms import Form

import clrというのが趣があります。

  • .NETから、Pythonのライブラリを .NET 上でimportできる
dynamic np = Py.Import("numpy");
var x = np.cos(np.pi * 2);

こっち方向は、 @hogegex さんの記事があります。

.NET (C#)からpythonを呼び出す

用途としては、Pythonから.NET独自のライブラリ(ビジネス系など)を呼び出したり、.NETから数値演算のタスクを投げたりなどが考えられます。Python上で.NETのGUIライブラリを使って、アプリを作れるのは中々良さそうですね。
ただ、私の用途はあくまでBayesServerのライブラリをPythonから呼ぶだけなので、以下のことができれば、おおむね完了です。

Python DataFrame -> .NET DataTable変換

BayesServerのリファレンスにはヘルパークラスとして、jpype1を使ったデータフレームのマッピングヘルパー関数が用意されています。

Pandas DataFrame helper functions

おそらく、jpype1を使った変換は癖があるので、こういったものを用意してくれていると思うのですが、pythonnetだともっとストレートに書けます。
ほぼ、コピペで.NET向けに書き直してみました。

# %%
import numpy as np
import pandas as pd
import clr
from System.Data import *
# %%
def _to_net_class(data_type):
    """
    Converts numpy data type to equivalent .NET class
    :param data_type: the numpy data type
    :return: The Net Class
    """
    if data_type == np.int32:
        return clr.GetClrType(Int32)  
    if data_type == np.int64:
        return clr.GetClrType(Int64)  
    if data_type == np.float32:
        return clr.GetClrType(Single) 
    if data_type == np.float64:
        return clr.GetClrType(Double) 
    if data_type == np.bool:
        return clr.GetClrType(Boolean) 
    if data_type == np.object:
        return clr.GetClrType(Object) 

    raise ValueError('dtype [{}] not currently supported'.format(data_type))

# %%
def to_data_table(df):
    data_table = DataTable()

    for name, data_type in df.dtypes.iteritems():
        net_class = _to_net_class(data_type)
        data_table.Columns.Add(str(name),net_class)

    for index, row in df.iterrows():
        xs = [None if pd.isnull(x) else x for x in row]
        data_table.Rows.Add(xs)

    return data_table

これで、pandasのデータをするっと.NETライブラリに持ち込めるので、いわゆるExcel表のようなGUIや、データベースとの交換も楽になるかもです。
clr.GetClrType()というのがtypeof(やObject.GetType())の代わりみたいなものだと思ってください。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした