1

私のタイトルは少しわかりにくいと思いますが、例を進めるとより明確になると思います。私がやりたいのは、特定のシリーズの値のいずれかが、startおよびstop列を持つ DataFrame オブジェクトによって定義された間隔のいずれかに含まれているかどうかを確認するベクトル化されたテストです。

validという名前の DataFrame の列であるシリーズ を考えてみましょうtrials。これが次のようなものtrialsです。

<class 'pandas.core.frame.DataFrame'>
Int64Index: 156 entries, 0 to 155
Data columns (total 3 columns):
start    156  non-null values
stop     156  non-null values
valid    156  non-null values
dtypes: bool(1), float64(2)

「blink」という別の DataFrame があります。次の 3 つの列があります。

<class 'pandas.core.frame.DataFrame'>
Int64Index: 41 entries, 0 to 40
Data columns (total 3 columns):
tstart    41  non-null values
tstop     41  non-null values
dur       41  non-null values
dtypes: bool(1), float64(2)

最後の列は直接関係ありません。それはアイブリックの期間、つまり と の差tstopですtstart

trials['valid']toの各行をFalse、対応するtrials['start']toの間隔がtoの間隔のいずれかtrials['stop']と重なる場合に設定したいと思います。blink['tstart']blink['tstop']

行を反復処理し、演算子と一緒に使用してネストされたループでこれを行うこともできますが、文字通り数時間かかります (実際のデータ セットは、このダミーの例よりもはるかに大きくなります)。使用できるベクトル化されたアプローチはありますか? そうでない場合、より高速な反復ベースのアプローチはありますか?np.arangein

ご不明な点がございましたら、もちろん喜んで追加の詳細をお知らせいたします。

4

2 に答える 2

1

あなたのまばたきデータ

In [27]: blink = pd.DataFrame(dict(tstart = [0,10], tstop = [5,15]))

In [28]: blink_s = blink.stack()

In [29]: blink_s.index = [ "%s_%s" % (v,i) for i, v in blink_s.index ]

一連のまばたき (ピボットのようなもの) を作成しますが、新しい名前が必要です

In [37]: blink_s
Out[37]: 
tstart_0     0
tstop_0      5
tstart_1    10
tstop_1     15

トライアルデータ

In [30]: trial = pd.DataFrame(dict(start = [3,7,12],stop=[4,10,16]))

トライアルの行全体にblink_sを並べて表示します

In [32]: blink_df = pd.DataFrame([ blink_s for i in trial.index ])

参加する

In [33]: x = trial.join(blink_df)

In [34]: x
Out[34]: 
   start  stop  tstart_0  tstop_0  tstart_1  tstop_1
0      3     4         0        5        10       15
1      7    10         0        5        10       15
2     12    16         0        5        10       15

あなたの答えはベクトル化されたブール式です(これはおそらく長いものになるので、プログラムで生成する必要がありますが、それを行うのはそれほど複雑ではありません)

In [35]: x['valid'] = ((x.start>x.tstart_0) & (x.stop<=x.tstop_0)) | ((x.start>x.tstart_1)&(x.stop<=x.tstop_1))

In [36]: x
Out[36]: 
   start  stop  tstart_0  tstop_0  tstart_1  tstop_1  valid
0      3     4         0        5        10       15   True
1      7    10         0        5        10       15  False
2     12    16         0        5        10       15  False

これは、float データを tstart/tstop 基準として使用する場合に機能します。間隔を int データのみに制限する場合、解決策は少し単純になります。これをすべて行う代わりに、含まれる一連の値 (blink_s など) を 1 つ作成し、isin.

要するに、まばたきフレームをシリーズにフラット化して、各トライアルに適用できるようにします。

Isin (および OP データ) の使用:

int64 データに変換

trial = pd.load('trials.pickle').reindex(columns=['start','stop']).astype('int64')
blink = pd.load('blink.pickle').astype('int64')

範囲が ni であることがわかっている行を追加します

trial = trial.append(pd.Series(dict(start=1000,stop=1200)),ignore_index=True)

テストしたい値の範囲を構築する

selections = []
for r in blink.iterrows():
    e = r[1]
    selections.extend(list(np.arange(e['tstart'],e['tstop'])))
selections = pd.Series(selections)

渡された開始/停止が選択範囲内にある場合は true を返します

def f(s):
    return s.isin(selections).all()
trial['valid'] = trial.apply(f,axis=1)

trial[trial.valid]

合格するとわかっていた 1 行を挿入しましたが、他の行は合格しませんでした

     start  stop valid
156   1000  1200  True
于 2013-04-07T17:39:23.080 に答える
0

trialsのサイズとmのサイズを想定しblinkますn

まず、 で各行をチェックblinkする前に で並べ替え、重なっている行をマージします。これを見てください。tstarttrialsO(n log n)

開始/停止ペアが有効かどうかを確認する間、次のアルゴリズムに従います。

  1. 二分探索を使用して、ソート済みの先頭を挿入しますtstarts
  2. 二分探索を使用して、ソート済みにストップを挿入しますtstarts
  3. start と stopの間に何かあればtstartTrue を返す
  4. 開始直前のものを探し、その を見つけ、tstopそれらが開始/停止のペアと重なる場合は True を返します
  5. 偽を返す

start/stop上記のアルゴリズムは、ペアがいずれかのペアと重複しているかblinkどうかをチェックするための時間の複雑さO(n)を軽減するのに役立つ場合がありますO(log n)。ここで、n は長さです。blink

時間の計算量は から に減少O(mn)O(m log n) + O(n log n)ます。m >> log nとが大きい場合n、それは大いに役立つかもしれません。

于 2013-04-07T18:41:49.943 に答える