2

私はこの種のパターンをたくさんコーディングしていることに気づきました:

tmp = <some operation>
result = tmp[<boolean expression>]
del tmp

... whereは、 を含む<boolean expression>ブール式として理解されるべきです。(当分の間、常に pandas データフレームですが、numpy ndarrays を使用している場合、同じパターンが表示されると思います-よくわかりません。) tmptmp

例えば:

tmp = df.xs('A')['II'] - df.xs('B')['II']
result = tmp[tmp < 0]
del tmp

del tmp最後から推測できるように、作成する唯一の理由tmpは、それに適用されるインデックス式内でブール式を使用できるようにするためです。

この(そうでなければ役に立たない)中間体の必要性をなくしたいのですが、これを行うための効率的な1つの方法はわかりません。(間違っていたら訂正してください!)

次善として、このパターンをいくつかのヘルパー関数にプッシュしたいと思います。問題は、適切な方法で を渡す<boolean expression>ことです。卑猥なことしか考えられない。例えば:

def filterobj(obj, criterion):
    return obj[eval(criterion % 'obj')]

これは実際に機能します2 :

filterobj(df.xs('A')['II'] - df.xs('B')['II'], '%s < 0')

# Int
# 0     -1.650107
# 2     -0.718555
# 3     -1.725498
# 4     -0.306617
# Name: II

...しかし、evalいつも使っていると気分が悪くなります...他の方法があれば教えてください。


1たとえば、ビルトインを含むと考えることができるアプローチfilterは、おそらく非効率的です。これは、パンダ (または numpy) オブジェクトに対して「Python で」反復することによって基準 (ラムダ関数) を適用するためです...

2上記の最後の式の used の定義はdf、次のようになります。

import itertools
import pandas as pd
import numpy as np
a = ('A', 'B')
i = range(5)
ix = pd.MultiIndex.from_tuples(list(itertools.product(a, i)),
                               names=('Alpha', 'Int'))
c = ('I', 'II', 'III')
df = pd.DataFrame(np.random.randn(len(idx), len(c)), index=ix, columns=c)
4

2 に答える 2

1

これは私が得ることができるのと同じくらい簡潔です:

(df.xs('A')['II'] - df.xs('B')['II']).apply(lambda x: x if (x<0) else np.nan).dropna()

Int
0     -4.488312
1     -0.666710
2     -1.995535
Name: II
于 2013-02-20T19:07:24.710 に答える
1

Python の仕組みのせいで、これは大変なことになると思います。私はあなたをそこへの道のりの一部だけにするハックしか考えられません. 何かのようなもの

def filterobj(obj, fn):
    return obj[fn(obj)]

filterobj(df.xs('A')['II'] - df.xs('B')['II'], lambda x: x < 0)

私が何かを見逃していない限り、うまくいくはずです。このようにラムダを使用することは、評価を遅らせるための通常のトリックの 1 つです。

大声で考えてください:this評価されずに式としてくっつくオブジェクトを作成できます。

>>> this
this
>>> this < 3
this < 3
>>> df[this < 3]
Traceback (most recent call last):
  File "<ipython-input-34-d5f1e0baecf9>", line 1, in <module>
    df[this < 3]
[...]
KeyError: u'no item named this < 3'

そして、thisパンダへの処理を特別なケースにするか、まだ次のような機能を持っています

def filterobj(obj, criterion):
    return obj[eval(str(criterion.subs({"this": "obj"})))]

(十分な作業を行うとeval、を失う可能性があります。これは単に概念の証明です)その後、次のような

>>> tmp = df["I"] + df["II"]
>>> tmp[tmp < 0]
Alpha  Int
A      4     -0.464487
B      3     -1.352535
       4     -1.678836
Dtype: float64
>>> filterobj(df["I"] + df["II"], this < 0)
Alpha  Int
A      4     -0.464487
B      3     -1.352535
       4     -1.678836
Dtype: float64

動作します。これが頭を悩ませるに値するものかどうかはわかりませんが、Python はこのスタイルにはあま​​り適していません。

于 2013-02-20T19:32:49.540 に答える