1

私はいくつかのログ分析を行っており、数分ごとにキューの長さを調べています。ファイルがいつ「キュー」(単純なファイルシステムディレクトリ)に入ったのか、いつ出たのかを知っています。これで、指定された間隔でキューの長さをプロットできます。これまでのところ、コードは少し手続き型ですが、これまでのところ良好です。

ts = pd.date_range(start='2012-12-05 10:15:00', end='2012-12-05 15:45', freq='5t')
tmpdf = df.copy()
for d in ts:
    tmpdf[d] = (tmpdf.date_in < d)&(tmpdf.date_out > d)
queue_length = tmpdf[list(ts)].apply(func=np.sum)

しかし、実際の長さと特定の消費率(たとえば、1秒あたり1つなど)での長さを比較したいと思います。キューはゼロを超えることができないため、定数を減算することはできません。

私はそれをしましたが、非常に手続き的な方法で。前の要素に対してすでに計算された結果にアクセスできないため、パンダのウィンドウ関数を使用しようとしましたが、ほとんど成功しませんでした。これは私が最初に試したもので、致命的な誤りでした。

imagenes_min = 60 * imagenes_sec
def roll(window_vals):
    return max(0.0, window_vals[-1] + window_vals[-2] - imagenes_min)

pd.rolling_apply(arg=imagenes_introducidas, func=roll , window = 2, min_periods=2)

実際のコードは次のようなものですが、冗長すぎて遅いと思います。

imagenes_sec = 1.05
imagenes_min = imagenes_sec * 60 *5
imagenes_introducidas = df3.aet.resample(rule='5t',how='count')
imagenes_introducidas.head()

def accum_minus(serie, rate):
    acc = 0
    retval = np.zeros(len(serie))
    for i,a in enumerate(serie.values):
       acc = max(0, a + acc - rate)
       retval[i] = acc
    return Series(data=retval, index=serie.index)

est_1 = accum_minus(imagenes_introducidas, imagenes_min)
comparativa = DataFrame(data = { 'real': queue_length, 'est_1_sec': est_1 })
comparativa.plot()

比較する

これは簡単な作業のようですが、適切に行う方法がわかりません。パンダはツールではないかもしれませんが、いくつかの厄介なまたはscipyの魔法です。

更新:df3は次のようになります(一部の列は省略されています):

                               aet             date_out
date_in                                               
2012-12-05 10:08:59.318600  Z2XG17  2012-12-05 10:09:37.172300
2012-12-05 10:08:59.451300  Z2XG17  2012-12-05 10:09:38.048800
2012-12-05 10:08:59.587400  Z2XG17  2012-12-05 10:09:39.044100

更新2:これは速いようですが、まだあまりエレガントではありません

imagenes_sec = 1.05
imagenes_min = imagenes_sec * 60 *5
imagenes_introducidas = df3.aet.resample(rule='5t',how='count')

def add_or_zero(x, y):
    return max(0.0, x + y - imagenes_min)

v_add_or_zero = np.frompyfunc(add_or_zero, 2,1)
xx = v_add_or_zero.accumulate(imagenes_introducidas.values, dtype=np.object)

dd = DataFrame(data = {'est_1_sec' : xx, 'real': queue_length}, index=imagenes_introducidas.index)
dd.plot()
4

1 に答える 1

2

インバウンドイベントとアウトバウンドイベントを1つのフレームにインターリーブするのはどうですか?

In [15]: df
Out[15]: 
                      date_in     aet                    date_out
0  2012-12-05 10:08:59.318600  Z2XG17  2012-12-05 10:09:37.172300
1  2012-12-05 10:08:59.451300  Z2XG17  2012-12-05 10:09:38.048800
2  2012-12-05 10:08:59.587400  Z2XG17  2012-12-05 10:09:39.044100

In [16]: inbnd = pd.DataFrame({'event': 1}, index=df.date_in)

In [17]: outbnd = pd.DataFrame({'event': -1}, index=df.date_out)

In [18]: real_stream = pd.concat([inbnd, outbnd]).sort()

In [19]: real_stream
Out[19]: 
                            event
date                             
2012-12-05 10:08:59.318600      1
2012-12-05 10:08:59.451300      1
2012-12-05 10:08:59.587400      1
2012-12-05 10:09:37.172300     -1
2012-12-05 10:09:38.048800     -1
2012-12-05 10:09:39.044100     -1

この形式(インクリメントごとに1つのデクリメント)では、キューの深さはcumsum()を使用して簡単に計算できます。

In [20]: real_stream['depth'] = real_stream.event.cumsum()

In [21]: real_stream
Out[21]: 
                            event  depth
date                                    
2012-12-05 10:08:59.318600      1      1
2012-12-05 10:08:59.451300      1      2
2012-12-05 10:08:59.587400      1      3
2012-12-05 10:09:37.172300     -1      2
2012-12-05 10:09:38.048800     -1      1
2012-12-05 10:09:39.044100     -1      0

さまざまな消費率をシミュレートするには、すべての実際のアウトバウンドタイムスタンプを、固定頻度で製造された一連のアウトバウンドタイムスタンプに置き換えます。この場合、cumsum()関数は機能しないため、フロア値をとるカウント関数を作成しました。

In [53]: outbnd_1s = pd.DataFrame({'event': -1},
   ....:                          index=real_stream.event.resample("S").index)

In [54]: fixed_stream = pd.concat([inbnd, outbnd_1s]).sort()

In [55]: def make_floor_counter(floor):
   ....:     count = [0]
   ....:     def process(n):
   ....:         count[0] += n
   ....:         if count[0] < floor
   ....:             count[0] = floor
   ....:         return count[0]
   ....:     return process
   ....: 

In [56]: fixed_stream['depth'] = fixed_stream.event.map(make_floor_counter(0))

In [57]: fixed_stream.head(8)
Out[57]: 
                            event  depth
2012-12-05 10:08:59            -1      0
2012-12-05 10:08:59.318600      1      1
2012-12-05 10:08:59.451300      1      2
2012-12-05 10:08:59.587400      1      3
2012-12-05 10:09:00            -1      2
2012-12-05 10:09:01            -1      1
2012-12-05 10:09:02            -1      0
2012-12-05 10:09:03            -1      0
于 2012-12-20T04:01:03.330 に答える