2016-11-12 26 views
3

私はパンダを使用して、人がコースの出席に関して前提条件を満たすかどうかを判断しています。以下のコードは望ましい結果を返しますが、私は同じ結果を達成するためのより良い方法があると確信しています。パンダでネストされたクエリ/複数のデータセットを効率的に比較

物理学を遂行できるかどうかを判断する基準は次のとおりです。

(Math_A OR Math_B OR Math_C) AND (Eng_A OR Eng_B) AND NOT (Physics) 

私の質問は、このタスクを達成するためにどのような効率性または代替方法を適用できるかということです。

ネストしたクエリなどを読み上げると、1つのクエリで複数のクエリを比較する方法を考え出すことができません。理想的には、人が前提条件を満たすかどうかをチェックする文を1つは持っていますが、これまでこれまでに失敗しています。

データセットは - ThxをBoud - 通常、読みやすさを簡素化するために改訂> 20,000レコード

Emplid,Name,CourseId,CourseName 
123,David,P12,Mathematics A 
123,David,P13,Mathematics B 
123,David,P14,Mathematics C 
123,David,P32,Engineering A 
456,Sally,P33,Engineering B 
789,Roger,P99,Physics 

コード

が含まれています。

import pandas as pd 

def physics_meets_prereqs(): 

    df = pd.DataFrame({'Emplid':['123','123', '123', '123', '456', '789'], 
        'Name':['David','David','David','David','Sally','Roger'], 
        'CourseId':['P12','P13','P14','P32','P33','P99'], 
        'CourseName':['Mathematics A','Mathematics B','Mathematics C','Engineering A','Engineering B', 'Physics'] 
        }) 

    # Get datasets of individually completed courses 
    has_math = df.query('CourseId == "P12" or CourseId == "P13" or CourseId == "P14"') 
    has_eng = df.query('CourseId == "P32" or CourseId == "P33"') 
    has_physics = df.query('CourseId == "P99"') 

    # Get personnel who have completed math and engineering 
    has_math_and_eng = has_math[(has_math['Emplid'].isin(has_eng['Emplid']))] 

    # Remove personnel who have completed physics 
    has_math_and_eng_no_physics = has_math_and_eng[~(has_math_and_eng['Emplid'].isin(has_physics['Emplid']))] 

    print(has_math_and_eng_no_physics) 

physics_meets_prereqs() 

出力

CourseId  CourseName Emplid Name 
0  P12 Mathematics A 123 David 
1  P13 Mathematics B 123 David 
2  P14 Mathematics C 123 David 

出力は、物理学コースのための前提条件を満たすものとして識別されているデビッドが得られています。それは私がまだ制限する方法を考え出していない彼を3回リストする。私はこれを達成している方法は間違いなく改善することができます。一言で言えば

は私の数学のコースの少なくとも一方、エンジニアリングのコースのうちの少なくとも一つを完了しているし、まだ物理学のコースを完了していない人のリストを表示します。

答えて

3
pivoted = df.groupby(['Name', df.CourseName.str.split().str[0]]) \ 
      .CourseId.size().gt(0).unstack(fill_value=False) 

pivoted 

enter image description here

matches = pivoted.query('Engineering & Mathematics & ~Physics') 
matches 

enter image description here

df.query('Name in @matches.index') 

enter image description here

+0

ああ私の神。あなたはウィザードです!いくつかのつまんでは、私は1つの賞金を持っていた質問のすべての束を解決します。どうもありがとうございます! – Dan

+3

いいえ、彼はただrubikscube ;-)が好きです – Boud

1

使用queryは、より自然な数学的関係を入力します

df.query('CourseId == "P12" or CourseId != "P99"') 
+0

CourseIdがP12の場合、P99と常に等しくありません。パンダは行を操作するので、提案はどのように改善されますか? – Dan

+1

またはに変更されました。 PCから離れているので、コードを実行することはできません。私の要点は、カスケード中間変数を作成する代わりに、クエリを使って実行すると、おそらくより柔軟で読みやすいということです。 – Boud

+0

それをクリアしました。クエリの読みやすさによってどこから来ているのかわかります。私が最初のやり方で行ったのは、他のコースを追加すると、これらの基準がプログラム中で複数回使用されるからです。私はそれがトラックの下でさらにクエリテキストを複製する必要がなくなったと考えました。提案していただきありがとうございます、私はそれがあなたのインスタンスで読むことが容易であることに同意します。 – Dan

関連する問題