質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.40%
Julia

Juliaとは、科学技術計算に特化した、高水準・高性能な動的プログラミング言語です。オープンソースとして公表されており、書き易く動きが早いことが特徴です。

Q&A

解決済

2回答

235閲覧

[Julia]データフレームのフィルターを早くする方法

akirayoshimura

総合スコア47

Julia

Juliaとは、科学技術計算に特化した、高水準・高性能な動的プログラミング言語です。オープンソースとして公表されており、書き易く動きが早いことが特徴です。

0グッド

0クリップ

投稿2024/05/04 04:21

実現したいこと

データフレームからリストに入っている値を取り出すコードを早くしたいと考えています。

Julia

1a = DataFrame(a = rand(1:10, 1000000), b = rand(1:3, 1000000)) 2testList = [1,2,3,4] 3a[in.(a.a, [testList]), :]

発生している問題・分からないこと

自身でいろいろ試した結果これが一番早かったのですが、実際のユースケースではこれがかなりの時間を消費しており改善したいと思っています。
実際は30個の値が入っている辞書をループし毎回255,856行, 12列のデータフレームから値を取り出す作業を行っています。

Julia

1for (key, val) in diffChecked 2 group = df[in.(df.val, [val]), :] 3end

Profviewを使用して使用時間を見てみたところ、構造としては上から
broadcast.jlのmaterialize→copy→copyto_nonleaf!→getindex→_broadcast_getindex→_broadcast_getindex_evalf→in
となっていました。

該当のソースコード

特になし

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

試しにfilter関数に変更してみたりsetを使用してみたりと変更を加えたのですがやはり元の形が一番早いという結果でした。

Julia

1a = DataFrame(a = rand(1:10, 1000000), b = rand(1:3, 1000000)) 2testList = [1,2,3,4] 3testList2 = Set([1,2,3,4]) 4 5a[in.(a.a, [testList]), :] 6filter(:a => in(testList2), a, view=true) 7 8テスト1 9@benchmark a[in.(a.a, [testList]), :] 10テスト2 11@benchmark filter(:a => in($testList2), $a, view = true)

テスト1では平均時間が8.184msだったのがテスト2では8.395msという結果でした。

補足

特になし

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

僕の質問への回答としてはujimushi_sradjpさんのものが最速です。
しかしそもそもデータフレームに対してinを使う事自体が遅かったので、先に条件に合うindicesをリストとして作成しそれを用いて新しいデータフレームを作成する事で数倍早くなりました。
※僕の例はdfが数百万行あり、辞書のループ毎に数十万行を抜き出す際の話です。

↓元のコード for (key, val) in diffChecked group = df[in.(df.val, [val]), :] end ↓改善版 for (key, val) in diffChecked inList = sorted_intersect2(df.val, sort(val)) group = df[inList, :] end

上記ではリンクで提示されている関数の戻り値に変更を及ぼしたものです。
しかしfindallを使用するやり方でも同様に早くなりました。

投稿2024/05/06 03:17

akirayoshimura

総合スコア47

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

ほぼ最速だと思いますが,実環境ではデータフレームの行数・列数が多いので,
result = df[条件,:]だと,条件に合致した行を抽出したデータフレームの新規作成
になり要素のコピーが発生し,そこで時間がかかっているのではないでしょうか?

例えば同じコードで@viewマクロを使ってみてはどうでしょう?
これなら抽出したデータフレームは元のaのビュー扱いとなるので,
要素のコピーが発生せず時間が減るのではないかと思います。

一応手持ちの環境での@benchmarkの例です。

julia

1julia> @benchmark @view a[in.(a.a, [testList]), :] 2BenchmarkTools.Trial: 1013 samples with 1 evaluation. 3 Range (min … max): 4.733 ms … 5.780 ms ┊ GC (min … max): 0.00%13.86% 4 Time (median): 4.896 ms ┊ GC (median): 0.00% 5 Time (mean ± σ): 4.934 ms ± 163.691 μs ┊ GC (mean ± σ): 0.52% ± 2.28% 6 7 ▃▄▅▇██▄▁ 8 ▂▁▂▃▃▅▆████████▅▃▃▂▂▁▁▂▂▂▁▁▂▁▁▂▂▁▁▁▁▁▂▁▁▂▂▁▃▃▃▂▃▂▂▁▁▂▂▂▂▃▃▃ ▃ 9 4.73 ms Histogram: frequency by time 5.59 ms < 10 11 Memory estimate: 3.17 MiB, allocs estimate: 11. 12 13julia> @benchmark a[in.(a.a, [testList]), :] 14BenchmarkTools.Trial: 808 samples with 1 evaluation. 15 Range (min … max): 5.918 ms … 8.107 ms ┊ GC (min … max): 0.00%10.39% 16 Time (median): 6.076 ms ┊ GC (median): 0.00% 17 Time (mean ± σ): 6.175 ms ± 285.954 μs ┊ GC (mean ± σ): 1.12% ± 2.83% 18 19 ▄▄█▆▅▁ 20 ▂▂▂▅███████▆▄▄▂▂▂▂▂▂▂▁▂▁▁▁▁▁▁▁▂▁▁▂▁▂▁▁▂▁▁▁▂▁▂▂▃▃▃▃▄▄▂▂▁▂▁▁▂ ▃ 21 5.92 ms Histogram: frequency by time 7.05 ms < 22 23 Memory estimate: 9.27 MiB, allocs estimate: 23.

追記

結果はDataFrameではなくSubDataFrameになるので,大元のDataFrameを変更すると変になったりするので,少し注意が必要かもしれません。

再追記

なお,テストについては,実際のDataFrameと同じ12列でやった方がいいと思います。
例えば次のように12列のデータフレームを設定した場合,

julia

1a = DataFrame( 2 NamedTuple(map(x -> x => rand(1:10, 1000000), Symbol.('a':'l'))) 3)

手元の環境だと

@benchmark a[in.(a.a, [testList]), :] : 12.929 ms
@benchmark filter(:a => in($testList2), $a, view = true) : 9.107 ms

と実行時間が逆転します。これはコピー有無の差ですね。

@benchmark @view a[in.(a.a, [testList]), :] : 4.746 ms

なので,これが一番速そうです。なお,蛇足ですが

df = @view a[in.(a.a, [testList]), :]

のような感じで使います。

投稿2024/05/04 15:23

編集2024/05/05 00:50
ujimushi_sradjp

総合スコア2124

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

akirayoshimura

2024/05/05 11:00

回答いただきありがとうございます! @viewを用いたところ144.562424sから144.024033sに短縮されました! 更に大きなデータを扱うときもあるので、そちらなどでは大きく改善しそうです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.40%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問