2017-05-01 4 views
2

私は観測時間を表す浮動小数点値のリストを持っています。 (各フロート値は実際には整数で表すことができますが、将来の可能性について一般化したいと考えています)。どのようにして、重複を含むソートされたリストの連続していないフロート要素の間に1つのパッドをゼロにすることができますか?

list_hrs = [4,6,8,8,10] # actual list is thousands of floats 

重複したエントリの唯一の発生をカウントしながら、私はパッドにゼロで、それぞれのインデックスに一致しない値をしようとしています。例えば、リストごとに、私は0から3に包括的に4つの数字があるので

list_hrs = [0,0,0,0,4,0,6,0,8,8,0,10] 

最初の4つのエントリが0をしているのでしょう。 5がないので、046の間にあります。 068の間で同様です。値9が存在しないため、0810の間にあります。また、複製の8はそのまま残しておきます。これは後で私のコードで扱います。 0のパディングの前に、複製の1つだけがカウントされるべきです(8)。私はその後、別のSOの記事を読んで、それが最初0年代のリスト、そのため長さがあるべきを作るのがベストだという印象を離れて来た

for index in range(len(list_hrs)): 
    if list_hrs != index: 
     list_hrs.insert(index, 0) 

>> [0, 0, 0, 0, 0, 4, 6, 8, 8, 10] 

私の最初の試みは、これを試してみました考慮するデータポイントの数に等しい。次に、ゼロ以外のエントリは0のエントリを置き換えることができます。だから、私は次のように試した:

def make_zeros(hrs=list_hrs): # make list of 0's 
    num_zer = int(max(hrs)) 
    list_zer = [0 for index in range(num_zer+1)] 
    return list_zer 

しかし、私はこのポイントの後に希望の結果を達成するための条件を実装する方法がわかりません。私はenumerateを使用してインデックスがそのインデックスの値と一致するかどうかを確認する方法があると考えていますが、重複したエントリ(上記の例の8のようなもの)のために続行する方法がわかりません。

この方法は継続的に使用するのに適していますか、目的の結果を達成するための効率的な/簡単な方法がありますか?助けやアドバイスをいただければ幸いです。

def make_zeros_vectorized(A, dtype=float): 
    a = np.asarray(A).astype(int) 
    idx = a + np.r_[0, (a[1:] == a[:-1]).cumsum()] 
    out = np.zeros(idx[-1]+1,dtype=dtype) 
    out[idx] = A 
    return out 

サンプルの実行 - -

+0

彼らはなぜ浮動小数点数がありますか、そこに10進数を期待していますか? '4.2'と言うように?もしそうなら、出力はどのように見えますか? – Divakar

+0

また、入力は常にソートされますか? – Divakar

+0

各フロートは実際には整数として解釈できます。サンプルリストは実際には '[4.0,6.0,8.0,8.0,10.0]'でなければなりません。私はコードを一般化することを望んでいました。しかし、整数の場合の解があれば、この場合はうまくいくでしょう。 – mikey

答えて

2

ここに1つのベクトル化のアプローチです関与

In [95]: A 
Out[95]: [4.0, 6.0, 8.0, 8.0, 10.0, 10.0, 10.0, 14.0, 16.0] 

In [96]: make_zeros_vectorized(A) 
Out[96]: 
array([ 0., 0., 0., 0., 4., 0., 6., 0., 8., 8., 0., 
     10., 10., 10., 0., 0., 0., 14., 0., 16.]) 

In [100]: A 
Out[100]: [4.0, 4.0, 4.0, 4.0, 6.0, 8.0, 8.0, 10.0, 10.0, 10.0, 14.0, 16.0] 

In [101]: make_zeros_vectorized(A) 
Out[101]: 
array([ 0., 0., 0., 0., 4., 4., 4., 4., 0., 6., 0., 
     8., 8., 0., 10., 10., 10., 0., 0., 0., 14., 0., 
     16.]) 

ステップ

入力リスト

In [71]: A = [4.0,6.0,8.0,8.0,10.0,10.0,10.0,14.0,16.0] 

配列に変換

In [72]: a = np.asarray(A).astype(int) 

In [73]: a 
Out[73]: array([ 4, 6, 8, 8, 10, 10, 10, 14, 16]) 

重複のマスクを作成します。このアプローチの中心は、累積合計を後で使用する予定のためです。累積加算場合重複が、真として表現された出力配列に入力配列値を配置するための増分インデックスとして使用される、増分値をもたらす

In [74]: a[1:] == a[:-1] 
Out[74]: array([False, False, True, False, True, True, False, False], dtype=bool) 

In [75]: (a[1:] == a[:-1]).cumsum() 
Out[75]: array([0, 0, 1, 1, 2, 3, 3, 3]) 

以前のように、開始時にゼロを追加「[1:] [ - 1] ==」1要素レスアレイをもたらしたであろうが

In [76]: np.r_[0, (a[1:] == a[:-1]).cumsum()] 
Out[76]: array([0, 0, 0, 1, 1, 2, 3, 3, 3]) 

重複がシフトされるように最後に、入力されたアレイに追加/ワンアップを添加し出力配列を割り当てるインデックスを与える

In [77]: a + np.r_[0, (a[1:] == a[:-1]).cumsum()] 
Out[77]: array([ 4, 6, 8, 9, 11, 12, 13, 17, 19]) 

これ以降の手順では、基本的に出力配列を作成し、先に取得したインデックスを使用してaの値を割り当てます。あなたがゼロまたはそれらの指標のマスクが必要な場合は


は、ここで修正されたバージョンです -

def get_zeros_mask(A): 
    a = np.asarray(A).astype(int) 
    idx = a + np.r_[0, (a[1:] == a[:-1]).cumsum()] 
    mask = np.ones(idx[-1]+1,dtype=bool) 
    mask[idx] = 0 
    return mask 

サンプルの実行 -

In [93]: A 
Out[93]: [4.0, 6.0, 8.0, 8.0, 10.0, 10.0, 10.0, 14.0, 16.0] 

In [94]: make_zeros_vectorized(A) 
Out[94]: 
array([ 0., 0., 0., 0., 4., 0., 6., 0., 8., 8., 0., 
     10., 10., 10., 0., 0., 0., 14., 0., 16.]) 

In [95]: get_zeros_mask(A) 
Out[95]: 
array([ True, True, True, True, False, True, False, True, False, 
     False, True, False, False, False, True, True, True, False, 
     True, False], dtype=bool) 

In [96]: np.flatnonzero(get_zeros_mask(A)) 
Out[96]: array([ 0, 1, 2, 3, 5, 7, 10, 14, 15, 16, 18]) 
+0

コードは完璧に動作します!あなたが何をしたのか分かっているなら、 'np.r_'はエントリーを一つのリストに連結します。 'cumsum'は累積されたものですが、実際にそのコード行は何ですか? – mikey

+0

説明をありがとう。他のコードは浮動小数点の扱いに関して柔軟性がありますが、このコードははるかに高速で、何千ものデータポイントに役立ちます。 – mikey

+0

ゼロが埋められるべきインデックスを見つけることは、実際に私の目的に役立ちます。そうすれば、観測時刻とその時刻の観測値は0になります(観測が発生しなかった時間は観測値がゼロに相当するため)。私はこの目的のためにこのコードを適応させることができませんでした。あなたは私の元の質問のための完全な実用的なコードを私に与えるために寛大でした。これを行う方法を見つけ出すのを助けてくれますか? 'out [idx] = A'を' out [not idx] = A'のようなものに変更しようとしていますか? (私は正しい構文を知らない)。 – mikey

1

ちょうど別の例:

list_hrs = [4,6,8,8,10] 
lh = iter(list_hrs) 
fit = range(int(max(list_hrs))+1) 

result = [0 if i not in list_hrs else next(lh) for i in fit for _ in range(list_hrs.count(i)) or [1]] 
+0

私はかつて「iter」を使ったことはありませんが、これは私には意味があります。代替のアプローチに感謝します。 – mikey

+0

あなたも大歓迎です:) – zipa

+0

このコードは浮動小数点も扱うことができるので、より汎用性があります。 – mikey

関連する問題