2016-07-26 22 views
5

大きなデータセット(> 200k)があり、ゼロシーケンスを値に置き換えようとしています。 2つ以上のゼロを持つゼロシーケンスはアーティファクトであり、それをnp.NANに設定することによって除去する必要があります。ゼロシーケンスを他の値に置き換えてください

私はSearching a sequence in a NumPy arrayを読みましたが、静的パターンがないため、私の要件に完全に一致しませんでした。

np.array([0, 1.0, 0, 0, -6.0, 13.0, 0, 0, 0, 1.0, 16.0, 0, 0, 0, 0, 1.0, 1.0, 1.0, 1.0]) 
# should be converted to this 
np.array([0, 1.0, 0, 0, -6.0, 13.0, NaN, NaN, NaN, 1.0, 16.0, NaN, NaN, NaN, NaN, 1.0, 1.0, 1.0, 1.0])  

さらに詳しい情報が必要な場合はお知らせください。 ありがとうございます!


結果:ここで答えを

おかげで、Divakarのソリューションは、私は彼のものを受け入れる最短最速である@のように私(素人)の試験結果は288240ポイント

divakar took 0.016000ms to replace 87912 points 
desiato took 0.076000ms to replace 87912 points 
polarise took 0.102000ms to replace 87912 points 

上で実行されています。

答えて

3

これは基本的に閉鎖ギャップにしきい値要件があるbinary closing operationです。ここでは、それに基づいた実装だ - 大きなデータセットを扱うとき、それは少し高価になるかもしれない境界要素、で動作するように、必要に応じて、以前の方法で追加することを避けるために

# Pad with ones so as to make binary closing work around the boundaries too 
a_extm = np.hstack((True,a!=0,True)) 

# Perform binary closing and look for the ones that have not changed indiicating 
# the gaps in those cases were above the threshold requirement for closing 
mask = a_extm == binary_closing(a_extm,structure=np.ones(3)) 

# Out of those avoid the 1s from the original array and set rest as NaNs 
out = np.where(~a_extm[1:-1] & mask[1:-1],np.nan,a) 

一つの方法、だろうそのように - ここで

# Create binary closed mask 
mask = ~binary_closing(a!=0,structure=np.ones(3)) 
idx = np.where(a)[0] 
mask[:idx[0]] = idx[0]>=3 
mask[idx[-1]+1:] = a.size - idx[-1] -1 >=3 

# Use the mask to set NaNs in a 
out = np.where(mask,np.nan,a) 
+0

チャームのように動作します - ありがとう! – ppasler

+0

@ppaslerあなたの大規模なデータセット(> 200K)で、リストされたアプローチが実行時にどのように機能するかを教えてください。 – Divakar

+0

確かに、質問の後の結果を参照してください – ppasler

1

はあなたのリストに使用できる機能です。

import numpy as np 

def replace(a_list): 
    for i in xrange(len(a_list) - 2): 
     print a_list[i:i+3] 
     if (a_list[i] == 0 and a_list[i+1] == 0 and a_list[i+2] == 0) or (a_list[i] is np.NaN and a_list[i+1] is np.NaN and a_list[i+2] == 0): 
      a_list[i] = np.NaN 
      a_list[i+1] = np.NaN 
      a_list[i+2] = np.NaN 
    return a_list 

リストは一方向にトラバースされているので、(0, 0, 0)または(NaN, NaN, 0)の2つの比較しかありません。0NaNに置き換えます。

+0

このソリューションをお寄せいただきありがとうございます。 'valueError:浮動小数点NaNを整数に変換できません' 'data [i] = np.NaN' – ppasler

+0

これをリストまたは' np.array'に適用していますか?私はあなたのようにそれを使用する必要があると思います: 'np.array(replace(the_list))' ... – polarise

+0

ヤップ、あなたはリストを使用して右です - ありがとう – ppasler

1

あなたは、各intfloatに変換されることに注意してください

あなた

[ 0. 1. 0. 0. -6. 13. nan nan nan 1. 16. nan nan nan nan] 
を与える itertoolsパッケージ

import numpy as np 
from itertools import groupby 

l = np.array([0, 1, 0, 0, -6, 13, 0, 0, 0, 1, 16, 0, 0, 0, 0]) 

def _ret_list(k, it): 
    # number of elements in iterator, i.e., length of list of similar items 
    l = sum(1 for i in it) 

    if k==0 and l>2: 
     # sublist has more than two zeros. replace each zero by np.nan 
     return [ np.nan ]*l 
    else: 
     # return sublist of simliar items 
     return [ k ]*l 

# group items and apply _ret_list on each group 
procesed_l = [_ret_list(k,g) for k,g in groupby(l)] 
# flatten the list and convert to a numpy array 
procesed_l = np.array([ item for l in procesed_l for item in l ]) 

print procesed_l 

groupbyを使用することができます。ここをクリックしてください:NumPy or Pandas: Keeping array type as integer while having a NaN value

+0

素晴らしい作品 - ありがとう!私は少し短いので@Divakarソリューションを優先します。 – ppasler

+0

'[1.0、1.0、1.0、1.0、0]'は '[NaN、NaN、NaN、NaN、0]'につながります。 – ppasler

+0

ああ、そうです。if文に別の条件を追加して私の答えを修正しました – desiato

関連する問題