電通総研 テックブログ

電通総研が運営する技術ブログ

世界で一番くわしい、Pandas ⇔ TabularData変換表

こんにちは、電通総研、Xイノベーション本部 AIトランスフォーメーションセンター所属の徳原光です。

以前、AndroidスマホでAIモデルを運用するために、Pandasの特徴量計算のコードをKotlin DataFrameを使用してKotlinに移植するための変換表を公開しました。

今度は、特徴量計算のコードをSwiftに移植するため、pandasとTabularDataの変換表を作成しました。

Pandas ⇔ TabularData変換表

自分がよく使用していた処理から(Pandas的に)基本的なものを抜粋しています。無理やり表にしているので改行が変ですがご容赦ください。

処理 pandas TaburalData ドキュメント
データフレーム生成 df = pd.DataFrame({ "A": [2, 4, 6, 8, 10], "B": [3, 6, 9, 12, 15], "C": [5, 10, 15, 20, 25], "G": ["a", "b", "c", "a", "b"] }) var df = DataFrame(dictionaryLiteral: ("A", [2, 4, 6, 8, 10]), ("B", [3.0, 6.0, 9.0, 12.0, 15.0]), ("C", [5, 10, 15, 20, 25]), ("G", ["a", "b", "c", "a", "b"])) ?
データフレーム読み込み df = pd.read_csv('hogehoge.csv') let fileURL = Bundle.main.url(forResource: "hogehoge", withExtension: "csv") else {    fatalError("File not found")}do {    let df = try DataFrame(contentsOfCSVFile: fileURL, options: options)    print("\(df)")} catch {    print("Error loading CSV: \(error)")} ?
冒頭表示 df.head() df.prefix(5) 公式ドキュメント
データフレームを縦に結合 pd.concat([df1, df2], axis=0) df1.append(df2) ?
列を取得 df[”A”] df[”A”] ?
行を取得 df.loc[0] df.rows[0]df.rows[2...5] 公式ドキュメント
行数を取得 len(df) df.rows.count 公式ドキュメント
条件にあうデータを抽出 df.loc[df["G"] == "a", :] df.filter(on: "G", String.self, { $0 == "a" }) ?
カラムの値を更新 df[”A”] = df[”A”] - 2 df["A"] = df["A"].map{ $0! - 2 } ?
カラム名のリストに該当するカラムを選択 list_col = ["A", "B"]df[list_col] df[ [ "A", "B" ] ] ?
カラム追加 df['D'] = 1df['D'] = df['C'] - df['B'] df.append(column: Column(name: "Integers", contents: [1, 1, 1, 1, 1])) ?
カラムを削除 df.drop("A") df.removeColumn("A") ?
カラム名をリストで取得 df.columns print(df.columns.map { $0.name }) ?
カラム内の値をリストで取得 df[”A”].to_list() df[”A”].map { $0 as! Double }
df[”A”].map { $0 as! Int}
?
カラム名を変更 df.rename(columns={'A': 'K'}) df2.append(column: Column(name:"K", contents: df["A"].map { $0 as! Int}))
«df2.removeColumn("A")
?
列の値を編集 df[”A”] = df[”A”] - 5 df[”A”] = df["A"].map{ $0! - 5 } ?
集計 df.groupby('G').agg(["count", "sum", "mean" ]) df.grouped(by: "G").sums("B", Double.self, order: .descending)
df.grouped(by: "G").means("B", Double.self, order: .descending)
公式ドキュメント
外部結合 result = pd.merge(df1, df2, on='D', how='inner') df2.joined(df3, on: ("A"))
df2.joined(df3, on: ("A"))
?

TabularDataの使用感

SwiftのTabularDataでAIモデル運用のための特徴量計算を実装した感想は、当たり前ですが、Python×Pandasと同じような使用感で実装を進めることはできませんでした。

やはりPython環境ではPandasだけではなくnumpyやmatplotlibといったライブラリも提供されているので、単純なPandasとTabularDataの機能差だけではなく、データサイエンスや単純な数値計算に関連するライブラリの充実度やネットに公開されている情報量の差によって思うようにSwift移植が進まない場面が多かったです。

学習データとなるネットの情報がすくないので当然ですが、生成AIによるコード生成もあまり有効ではありませんでした・・・。

Kotlin DataFrameと比較してどうだったかというと、Kotlin DataFrameと比較してもかなり苦戦しましたね。

Python→Kotlin→Swiftと実装していたので、だんだん難易度が上がって情報不足に慣れながら実装できたので良かったですが、TabularDataはKotlin DataFrameと比較して公式が出している情報量も少なく、さらにGithub上で公開されているTabularDataを使ったソースコードの量も少なかったです。

また、Kotlinでの実装はJavaの豊富なライブラリを使用できることができますが、Swiftではそうはいかず、IoT機器としてAIモデルを運用するとしたら、AndroidよりiOSのほうが難易度が高いと感じました。

AndroidIOSでの機械学習モデルの運用

ちなみにモデルの運用は、AndroidではONNX RuntimeiOSではCore MLを使用しました。モデルのメタ情報についてXcodeGUIで確認できる、運用のためのクラスが自動で生成されるという点でCoreMLのほうが使用感は良かったですね。

Pythonで提供されている専用のモジュールでモデルを出力し、そのデータをXcode上でプロジェクトの適当なグループに追加すれば、あとはモデル名と同名のクラスを呼びだすだけで使えてかなり工数を節約できました。

ただ、Flutterプロジェクトで使用するとプロジェクト開発言語をObjective-CからSwiftに明示的に設定を変えないと動かない問題や、対応している機械学習モデルが少ない問題(LightGBMが使えない)、対応していてもモデルの提供ライブラリのバージョンを落とさないと使えない問題がCoreMLにはありました。

TabularDataを使用するために確認しておいたほうがいい情報

developer.apple.comでは、TabularDataの紹介動画が公開されています。TabularDataを使って住所情報を分析するデモンストレーションが行われているので、こちらは必ず確認したほうが良いと思います。

developer.apple.com

あと、こちらの記事はサンプルコードが載っているのでよく見ていました。

swdevnotes.com

いかのサイトに今回の変換表を作るにあたって使用したサンプルコードをおいています。

pickerlab.net

とにかく情報不足に陥るので、活用できる情報は一通り見ておくことをお勧めします。とりあえず、今回のAIモデルをスマホで運用するという1件を通して実装スキルが向上したなと感じました。

ちなみに、実装後のアプリの挙動はどうだったかというと、スマホのスペック不足を心配していましたが快適です。やはり最近のモバイル端末は一昔前のPC並に高いので、定番のモデルでしたら運用できますね。

最後に、私が所属しているAIトランスフォーメーションセンターでは、一緒に働いてくださる方を募集しております。こちらのページに採用に関する内容がまとめられております。また、カジュアル面談の募集もこちらのページからできますので、是非ご覧ください。

aitc.dentsusoken.com

それでは。

執筆:@tokuhara.hikaru、レビュー:@yamashita.tsuyoshi
Shodoで執筆されました