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

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

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

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

Q&A

解決済

2回答

846閲覧

[Julia] DFの新列作成時に条件に合った場合のみ値を入力する方法

akirayoshimura

総合スコア43

Julia

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

0グッド

0クリップ

投稿2022/11/08 23:12

編集2022/11/11 10:40

下記の様な二つのデータフレームがあり、data_frameに新しい列Dを作成しようと思っています。
列Dはdata_frameとmatchの列A, Bのが一緒の時にmatchの列Cの値、一致しない場合はXを記入したいのですがそれぞれの列をeachrowで回す処理をしていたのですが、速度が遅い為それ以外の実行速度が速い方法をお教えいただけますでしょうか?
(実際のユースケースではdata_frameが100万行、matchが4000行のデータフレームですので、一件一件の速度を重要視しています。)

Julia

1data_frame = DataFrame( 2 A = [1, 1, 1, 1, 2, 2, 2, 2], 3 B = [0, 1, 1, 0, 0, 0, 0, 1], 4 C = rand(8) 5) 6 7match = DataFrame( 8 A = [1, 2, 1, 1, 1, 2, 1, 2], 9 B = [1, 1, 1, 0, 0, 1, 0, 1], 10 C = ["A", "B", "C", "D", "A", "B", "C", "D"] 11)

最終的な完成形は下記の様にしたいです。
イメージ説明

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

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

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

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

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

guest

回答2

0

※ Benchmark

julia

1using DataFrames 2using BenchmarkTools 3 4function replace_by_ifelse(dfA, dfB) 5 dfA.D = ifelse.((dfA.A .== dfB.A) .& (dfA.B .== dfB.B), dfB.C, "X") 6 return dfA 7end 8 9function replace_by_transform(dfA, dfB) 10 transform!(hcat(dfA, dfB, makeunique=true), [:A, :B, :A_1, :B_1, :C_1] 11 => ByRow((a1, b1, a2, b2, c) -> (a1 == a2) & (b1 == b2) ? c : "X") 12 => :D)[!, append!(names(dfA), ["D"])] 13end 14 15data_frame = DataFrame( 16 A = [1, 1, 1, 1, 2, 2, 2, 2], 17 B = [0, 1, 1, 0, 0, 0, 0, 1], 18 C = rand(8) 19) 20 21match_frame = DataFrame( 22 A = [1, 2, 1, 1, 1, 2, 1, 2], 23 B = [1, 1, 1, 0, 0, 1, 0, 1], 24 C = ["A", "B", "C", "D", "A", "B", "C", "D"] 25) 26 27@btime replace_by_ifelse(data_frame, match_frame) 28# => 1.788 μs (10 allocations: 480 bytes) 29 30data_frame = DataFrame( 31 A = [1, 1, 1, 1, 2, 2, 2, 2], 32 B = [0, 1, 1, 0, 0, 0, 0, 1], 33 C = rand(8) 34) 35 36@btime replace_by_transform(data_frame, match_frame) 37# => 119.151 μs (496 allocations: 36.24 KiB)

投稿2022/11/09 18:17

編集2022/11/10 17:25
melian

総合スコア19618

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

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

akirayoshimura

2022/11/11 01:40

melianさん回答いただきありがとうございます。 速度まで書いていただき大変助かりました。
guest

0

ベストアンサー

eachrowを使った方が動作が速いと思いますが,ソースの行数を減らすことを優先すると次のような感じでしょうか?
df[boolのVector, :列名]trueのところの要素を選択できるので,それを使います。
Vector型の要素毎の比較で.のブロードキャスト演算子を濫用しています。
2つのデータフレームの行数チェックを省略しています。

なお,df[!, :列名]df.列名は同じ意味で,列名のVector型が返ってきます。
また,df[k, :列名]df.列名[k]も同じ意味です。
matchの名前は標準関数にあるので,先頭にアンダーバーをつけています。

julia

1using DataFrames 2 3data_frame = DataFrame( 4 A = [1, 1, 1, 1, 2, 2, 2, 2], 5 B = [0, 1, 1, 0, 0, 0, 0, 1], 6 C = rand(8) 7) 8 9_match = DataFrame( 10 A = [1, 2, 1, 1, 1, 2, 1, 2], 11 B = [1, 1, 1, 0, 0, 1, 0, 1], 12 C = ["A", "B", "C", "D", "A", "B", "C", "D"] 13) 14 15function add_D!(df::AbstractDataFrame, df_cmp::AbstractDataFrame) 16 df[!, :D] = Vector{String}(undef, nrow(df)) 17 is_match = df[!, :A] .== df_cmp[!, :A] .&& df[!, :B] .== df_cmp[!, :B] 18 df[is_match, :D] = df_cmp[is_match, :C] 19 df[.!is_match, :D] .= "X" 20end

結果

julia> include("test.jl") add_D! (generic function with 1 method) julia> add_D!(data_frame, _match) 5-element view(::Vector{String}, [1, 2, 5, 6, 7]) with eltype String: "X" "X" "X" "X" "X" julia> data_frame 8×4 DataFrame Row │ A B C D │ Int64 Int64 Float64 String ─────┼───────────────────────────────── 1 │ 1 0 0.356792 X 2 │ 1 1 0.0732795 X 3 │ 1 1 0.263522 C 4 │ 1 0 0.964729 D 5 │ 2 0 0.325033 X 6 │ 2 0 0.0382429 X 7 │ 2 0 0.374391 X 8 │ 2 1 0.566343 D

投稿2022/11/09 03:04

ujimushi_sradjp

総合スコア2066

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

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

akirayoshimura

2022/11/09 04:04

ujimushi_sradjpさん回答いただきありがとうございます。 なるほど、このように記載できるのですね。 ちなみにtransformで記載する方法はありませんでしょうか? 実際に使用するデータベースはdata_frameの受け手側が100万行以上、matchの送り手側が3000行ありeachrowだとかなりの時間がかかっていました。 以前からtransformが早いイメージがありましたので、eachrowより効率的な方法がありましたらお教えいただけると大変助かります。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問