2017-12-01 10 views
0

年が範囲を上回るか下回る場合、データフレームに異なるフィルタを適用したいと思います。ここではデータフレームパンダ:年に基づいてデータフレームに異なるフィルタを適用する

dataset=pd.DataFrame({'ID': [1,1,1,2,2,2,3,3,3,4,4,4,5,5,5], 
         'Avail' : [2017,2017,2017,2018,2018,2018,2017,2017,2017,2017,2017,2017,2017,2018,2018], 
         'Change' : [0,0,2018,0,0,0,0,0,0,0,0,0,2018,0,0], 
         'Pref' : [1,2,3,1,2,3,1,2,3,1,2,3,1,2,3], 
         'Status': ['null', 'null','Q','null','null','null','Q','null','null','null','null','null','Q','null','null'] 
         },columns=['ID', 'Avail', 'Change', 'Pref', 'Status']) 

ここではエラーを生成し、私が書いたコードがあるさ:

def yearfilt(x): 
    if x.loc[:, ['Avail', 'Change']].values.max(axis=1) < 2018: 
     if pd.isnull(x.Status): 
      x.drop_duplicates(subset=['STU_ID','Status' ], keep='last') 
     else: 
      x=x.drop(x[pd.isnull(x.Status)].index) 
    else: 
     if pd.isnull(x.ASSESSMENT_OUTCOME_CD): 
      x.drop_duplicates(subset=['STU_ID','Status' ], keep='first') 
     else: 
     x=x.drop(x[pd.isnull(x.Status)].index) 

df=dataset.groupby(['ID']).apply(yearfilt).sort_values(["ID"]).reset_index(drop=True) 

エラーは、私が実行したいと思い何

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all() 

です:

If the max (Avail, Change) < 2018 then 
Case 1: the same status --> drop duplicates and keep the last 
Case 2: different status --> drop null-value statuses 

else (in other words max (Avail, Change) = 2018) 
Case 1: the same status --> drop duplicates and keep the first 
Case 2: different status --> drop null-value statuses 

出力は次のようになります:

ID Year Change Pref Status 
1 2017 2018 3  Q 
2 2018 0  1  null 
3 2017 0  1  Q 
4 2017 0  3  null 
5 2017 2018 1  Q 

基本的に、各IDから1つだけを保持したいと思います。 ありがとう

+0

問題を起こしている行を書き留めてください。 –

+0

コードの最後の行:df = dataset.groupby(['ID'])。apply(yearfilt).sort_values(["ID"])。reset_index(drop = True) – Omido

答えて

1

ValueErrorif(some_series)をチェックしようとしているために表示されます。あなたが指定したエラーをどの行に示しているのかわかりませんが、if文のいずれかがこの問題を引き起こす可能性があります。

たとえば、最初のif文は、一連の値を単一の値と比較します。結果は一連のブール値であり、if文が意味を成すことができる単一のTrue/Falseではありません。同じことがpd.isnullで発生する可能性があります。

どのコマンドで配列結果が得られたのかを確認し、コードのロジックにどのように適合するか考えてください。私が正しくあなたの問題を理解していた場合

ここで可能な解決策は、です:物事の

def yearfilt(group): 
    # Apply .max() twice to get a single value across the group. 
    # Otherwise the results is a Series, and using if will result in a ValueError. 
    if group[['Avail', 'Change']].max().max() < 2018: 
     # Returns true if there is a unique status value. 
     if group['Status'].unique().shape[0] == 1: 
      # Return last row as a dataframe. 
      return group.iloc[-1:] 
     else: 
      # Return ALL rows with status not null (may be more than 1?). 
      return group[group['Status'] != 'null'] 
    else: 
     if group['Status'].unique().shape[0] == 1: 
      # Return first row as a dataframe. 
      return group.iloc[:1] 
     else: 
      return group[group['Status'] != 'null'] 

dataset.groupby('ID').apply(yearfilt).reset_index(drop=True) 

カップルは覚えている:

  • あなたはgroupby().applyに使う関数に渡された各引数が渡されますデータフレーム全体のサブセット。 return新しいオブジェクトを必要とし、関数が受け取るグループを変更しないでください。
  • あなたがisnullを使用している場合は、フィルタリングしようとしている値は、などNone、ない文字列'null''None''nan'、欠損値のthe docsを参照してくださいする必要があります。
  • ifステートメントは、Seriesには1つの値しか使用できません。
+0

ありがとうございます。しかし、上記のケース1,2で説明したように、年に基づいてフィルタを適用するよう提案していますか?私は本当にこのビットで立ち往生しています – Omido

+0

可能な解決策で投稿を編集しました。それが役に立てば幸い! –

+0

これは金です、ありがとうございます。これは私が提供したデータサンプルでうまく機能します。しかし、約30列の私の拡張データフレームにそれを適用すると、何かがオフになっているようです。私はフィルタが一貫した答えを与えない理由を理解しようとしています。実際のデータセットには列が増えていますが、フィルタに適用するために私の投稿のサンプルで提供した列のみを使用します。それはおかしい! – Omido

関連する問題