2017-10-29 6 views
0

データベースの時系列を大量に(> 100.000)検索します。一つの時系列が各エントリは8つの値を保持し、5〜10のエントリと2Dのリストである:異なるサイズのサブリストを持つビッグリストをパッディングNumPy配列に効率的に変換

single_time_series = [ 
     [ 43, 1219, 1065, 929, 1233, 2604, 3101, 2196], 
     [ 70, 1148, 1041, 785, 1344, 2944, 3519, 3506], 
     [ 80, 1148, 976, 710, 1261, 2822, 3335, 3247], 
     [ 103, 1236, 1090, 762, 1024, 2975, 3777, 3093], 
     [ 120, 883, 937, 493, 1221, 4119, 5241, 5133], 
     [ 143, 1110, 1089, 887, 1420, 2471, 2905, 2845] 

] # a time series with 6 entries, each entry represents one day 

更なる処理のために、私は1つの3D numpyのアレイに一緒にこれらの個々の時系列の全てが欲しいです。各シリーズの長さは5と10のエントリの間で変動し得るので、しかし、私はパッドにあるすべての時系列を必要とするゼロで埋め-アレイとより短い10:

[ 
    [ 43, 1219, 1065, 929, 1233, 2604, 3101, 2196], 
    [ 70, 1148, 1041, 785, 1344, 2944, 3519, 3506], 
    [ 80, 1148, 976, 710, 1261, 2822, 3335, 3247], 
    [ 103, 1236, 1090, 762, 1024, 2975, 3777, 3093], 
    [ 120, 883, 937, 493, 1221, 4119, 5241, 5133], 
    [ 143, 1110, 1089, 887, 1420, 2471, 2905, 2845], 
    [ 0, 0, 0, 0, 0, 0, 0, 0], 
    [ 0, 0, 0, 0, 0, 0, 0, 0], 
    [ 0, 0, 0, 0, 0, 0, 0, 0], 
    [ 0, 0, 0, 0, 0, 0, 0, 0] 
] 

現在、私はそれぞれを反復処理することによって、これを達成しています時系列は、データベースから来て、それをパディングし、最終numpyの配列にそれを追加:

MAX_SEQUENCE_LENGTH = 10 
all_time_series = ... # retrieved from db 

all_padded_time_series = np.array([], dtype=np.int64).reshape(0, MAX_SEQUENCE_LENGTH, 8) 

for single_time_series in all_time_series: 
    single_time_series = np.array(single_time_series, dtype=np.int64) 

    length_diff = MAX_SEQUENCE_LENGTH - single_time_series.shape[0] 

    if length_diff > 0: 
    single_time_series = np.pad(single_time_series, ((0, length_diff), (0,0)), mode='constant') 

    all_padded_time_series = np.append(all_padded_time_series, [single_time_series], axis=0) 

データベース要求は、ほんの数秒で実行している間、パディングと追加の操作は永遠に取る - スクリプトが必要〜45私のiMacの〜100.000時系列の分。

データベースが成長を続けているので、近い将来さらに多くのデータを分析する必要があります。だから私はdbから来るリストをnumpyの配列に変換するより速い方法を探しています。これを行うより効率的な方法があると確信しています。

+1

代わりに 'numpy.concatenate'を試しましたか?私の経験では、 'numpy.pad'はこの種のパディングでは非常に遅いです。 – cberkay

+0

関連性:https://stackoverflow.com/questions/32037893/numpy-fix-array-with-rows-of-different-lengths-by-filling-theempty-elements-wi – cberkay

+0

「np.append」を繰り返した遅すぎる。各配列を3dの '0 '配列にコピーする方がよいでしょう。または@Divakars 2dソリューションを適応させます。あなたはすでに、埋め込まれた配列の形状を知っています。 – hpaulj

答えて

0

あなたは2人の主要な時間消費者 - np.appendnp.padがあります。この追加は毎回新しい配列を作成します。 list.appendのようにリストは成長しません。 padは大丈夫ですが、より一般的なことは必要なものであり、したがって遅くなります。あなたがターゲット寸法を知っているので、すぐにゼロ埋め配列を作る

とコピーあなたのリスト

all_padded_time_series = np.zeros((len(all_time_series, MAX_SEQUENCE_LENGTH, 8), dtype=np.int64) 

for i, single_time_series in enumerate(all_time_series): 
    single_time_series = np.array(single_time_series, dtype=np.int64) 
    all_padded_time_series[i, :single_time_series.shape[0], :] = single_time_series 

またはコピーをさせる配列への変換を実行します。

for i, single_time_series in enumerate(all_time_series): 
    all_padded_time_series[i, :len(single_time_series), :] = single_time_series 

をコメントリンクへ@Divakarによる良い解決策。マスクを使用して、すべてのコンポーネント配列をターゲットに一度にコピーします。書かれているように、コンポーネントが1dであると仮定しますが、この2dの場合に適合させることができます。しかし、論理を理解して覚えておくことは難しいです(私は数回再作成しましたが)。

itertools.zip_longestもさまざまな長さのリストを結合するのに便利ですが、この2dのケースでうまく機能しません。maskを用いて算出されるNumpy: Fix array with rows of different lengths by filling the empty elements with zeros

の適応

In [269]: alist = [(np.ones((i,4),int)*i).tolist() for i in range(1,5)] 
In [270]: alist 
Out[270]: 
[[[1, 1, 1, 1]], 
[[2, 2, 2, 2], [2, 2, 2, 2]], 
[[3, 3, 3, 3], [3, 3, 3, 3], [3, 3, 3, 3]], 
[[4, 4, 4, 4], [4, 4, 4, 4], [4, 4, 4, 4], [4, 4, 4, 4]]] 
In [271]: res = np.zeros((4,4,4),int) 
In [272]: for i,x in enumerate(alist): 
    ...:  res[i,:len(x),:] = x 
    ...:  
In [273]: res 
Out[273]: 
array([[[1, 1, 1, 1], 
     [0, 0, 0, 0], 
     [0, 0, 0, 0], 
     [0, 0, 0, 0]], 

     [[2, 2, 2, 2], 
     [2, 2, 2, 2], 
     [0, 0, 0, 0], 
     [0, 0, 0, 0]], 

     [[3, 3, 3, 3], 
     [3, 3, 3, 3], 
     [3, 3, 3, 3], 
     [0, 0, 0, 0]], 

     [[4, 4, 4, 4], 
     [4, 4, 4, 4], 
     [4, 4, 4, 4], 
     [4, 4, 4, 4]]]) 

:それはres[0,:1,:], res[1,:2,:], etcを選択効果で

In [291]: mask = np.arange(4)<np.array([len(x) for x in alist])[:,None] 
In [292]: mask 
Out[292]: 
array([[ True, False, False, False], 
     [ True, True, False, False], 
     [ True, True, True, False], 
     [ True, True, True, True]], dtype=bool) 

。私たちは、上記の計算からresを見ることで確認することができた。

In [293]: res[mask] 
Out[293]: 
array([[1, 1, 1, 1], 
     [2, 2, 2, 2], 
     [2, 2, 2, 2], 
     [3, 3, 3, 3], 
     [3, 3, 3, 3], 
     [3, 3, 3, 3], 
     [4, 4, 4, 4], 
     [4, 4, 4, 4], 
     [4, 4, 4, 4], 
     [4, 4, 4, 4]]) 
我々は一つの長い2D配列にリストを連結することによって、同じ2D配列を得ることができます

In [294]: arr = np.concatenate(alist, axis=0) 

そしてこうしてマスクされた割り当てを行います:

In [295]: res[mask] = arr 

mask計算は視覚化して覚えにくいです。

+0

良い解決策は、これは対OPのソリューションをプロファイルし、あなたが明らかに速いはずですが、タイミングを比較することは興味深いでしょう。 – cberkay

+0

私はゼロ充填型のソリューションを試してみましたが、それは〜40秒に短縮されました。 – csch

+0

マスキングも面白そうに見えて、他にも興味深いかもしれません。 – csch

0
import numpy as np 
ll = [[43, 1219, 1065, 929, 1233, 2604, 3101, 2196], 
     [70, 1148, 1041, 785, 1344, 2944, 3519, 3506], 
     [80, 1148, 976, 710, 1261, 2822, 3335, 3247], 
     [103, 1236, 1090, 762, 1024, 2975, 3777, 3093], 
     [120, 883, 937, 493, 1221, 4119, 5241, 5133], 
     [143, 1110, 1089, 887, 1420, 2471, 2905, 2845]] 
     # your input list of lists from a database 

def a(l): 
    a = np.zeros((10, 8), dtype=np.int64) 
    np.copyto(a[0:len(l), 0:8], l) 
    return a 
    # my solution for this problem. 
    # this solution initializes nd-array at a time, 
    # so this may enable to rid the re-creation cost of nd-array. 

def b(l): 
    a = np.array(l, dtype=np.int64) 
    len_diff = 10 - a.shape[0] 
    return np.pad(a, ((0, len_diff), (0, 0)), mode='constant') 
    # your solution for this problem 

これらのコードをプロファイルして比較したいが、(CPUキャッシュのために)プロファイリングがうまくいかない。

+0

私はあなたの(cschの)質問を注意深く見ています.3次元配列を作成するには、all_time_seriesの数を数えて3d numpy配列の形状を定義するだけで済むからです。また、すべてのデータを1つずつ3darrayにコピーすることができます。 –

+0

また、再計算が必要ない場合、またはこの計算が過去のヒステリシスに関係しない場合は、レイジーシーケンス(iterable)を使用するか、この目的のために中間計算を保存します。 –

+0

https://stackoverflow.com/a/32043366/3712254についてどう思いますか? – cberkay

関連する問題