2016-10-27 16 views
1

以下の最小限の例では、pandas.DataFrame.applyメソッドを自分のメソッドsafe_applyでラップします。この方法は、2つの方法で、通常のapply異なりますPythonのtry-catch-raise例外節の2回振る舞い

  1. 代わりNDFrameの値を返すので、それはリスト、resultsにそれらを追加します。
  2. 例外がキャッチされると、エラーが発生して実行が終了する前にresultsが出力されます。ここ

コードである:

from pandas.core.frame import DataFrame, Series 
import pandas as pd 

def safe_apply(df, func, **kwargs): 
    results = [] 

    def new_func(srs): 
     try: 
      results.append(func(srs)) 
     except Exception as e: 
      print(results) 
      raise 

    df.apply(new_func, **kwargs) 
    return results 

DataFrame.safe_apply = safe_apply 

def f(srs): 
    if (pd.notnull(srs['lat'])) & (pd.notnull(srs['long'])): 
     return srs['lat'] + srs['long'] 
    else: 
     raise ValueError 


ex = pd.DataFrame({'lat': [1, 2, None], 'long': [1, 2, None]}, index=['A', 'B', 'C']) 
ex.safe_apply(f, axis='columns') 

私はこれを実行すると、Iはexの最初の2行に機能fを適用した後、第三のに失敗の結果を除い:のうちprintValueError

続い[2.0, 4.0]は、代わりに、私は、出力のValueError2つの行を取得する:

コードは、例外節に到達 resultsをプリントアウトし、その代わりにエラーをスローし、停止、次いで、 が何らかの形で(?)再び機能を実行することを意味
[2.0, 4.0] 
[2.0, 4.0, 2.0, 4.0] 
--------------------------------------------------------------------------- 
ValueError        Traceback (most recent call last) 
<ipython-input-1-382c07ef0919> in <module>() 
    26   raise ValueError 
    27 
---> 28 ex.safe_apply(f, axis='columns') 

<ipython-input-1-382c07ef0919> in safe_apply(df, func, **kwargs) 
    12    raise 
    13 
---> 14  df.apply(new_func, **kwargs) 
    15 
    16  return results 

C:\Users\Alex\Anaconda3\lib\site-packages\pandas\core\frame.py in apply(self, func, axis, broadcast, raw, reduce, args, **kwds) 
    4059      if reduce is None: 
    4060       reduce = True 
-> 4061      return self._apply_standard(f, axis, reduce=reduce) 
    4062    else: 
    4063     return self._apply_broadcast(f, axis) 

C:\Users\Alex\Anaconda3\lib\site-packages\pandas\core\frame.py in _apply_standard(self, func, axis, ignore_failures, reduce) 
    4155    try: 
    4156     for i, v in enumerate(series_gen): 
-> 4157      results[i] = func(v) 
    4158      keys.append(v.name) 
    4159    except Exception as e: 

<ipython-input-1-382c07ef0919> in new_func(srs) 
     7  def new_func(srs): 
     8   try: 
----> 9    results.append(func(srs)) 
    10   except Exception as e: 
    11    print(results) 

<ipython-input-1-382c07ef0919> in f(srs) 
    24   return srs['lat'] + srs['long'] 
    25  else: 
---> 26   raise ValueError 
    27 
    28 ex.safe_apply(f, axis='columns') 

ValueError: occurred at index C 

これはなぜ発生するのですか?

答えて

4

は、具体的

現在の実装では、docstringのノートセクションを参照の呼び出しを適用FUNC倍それが高速または低速コードパスを取ることができるかどうかを決定するために最初の列/行目。 funcに副作用があると、最初の列/行に対して2回有効になるため、予期しない動作につながる可能性があります。