2012-01-25 35 views
1

欠損値(None)を直前の既知の値で置き換えたいと思います。これは私のコードです。しかし、それは動作しません。より良いアルゴリズムのための任意の提案? index方法は、あなたがそれに渡す引数の最初の発生を返すためですPythonで欠損値を代入する

t = [[1, 3, None, 5, None], [2, None, None, 3, 1], [4, None, 2, 1, None]] 
def treat_missing_values(table): 
    for line in table: 
     for value in line: 
      if value == None: 
       value = line[line.index(value)-1] 
    return table 

print treat_missing_values(t) 
+0

"前回の既知の値"はどういう意味ですか?現在のリスト( "行")の以前の非None値を意味しますか?現在のリストの以前の値がNoneの場合はどうなりますか?前のリスト( "行")の最後の値を使用しますか?最初の値がNoneの場合はどうなりますか? –

+0

いいえ、行内に以前の値がない場合は、Noneを保持します。データは別々です。私は問題を見たが、質問を複雑にしたくなかった。 – Randomtheories

+0

**参照:** https://stackoverflow.com/questions/20248355/how-to-get-python-to-gracefully-format-none-and-non-existing-fields – dreftymac

答えて

0

EDIT1

# your algorithm won't work if the line start with None 
t = [[1, 3, None, 5, None], [2, None, None, 3, 1], [4, None, 2, 1, None]] 
def treat_missing_values(table): 
    for line in table: 
     for index in range(len(line)): 
      if line[index] == None: 
       line[index] = line[index-1] 
    return table 

print treat_missing_values(t) 
+1

範囲内のインデックス(len (ライン)) – RanRag

+1

シングルトンとの比較に 'is'を使用 – wim

+0

xrangeはPython 2.Xを使用するとさらに良いでしょう –

2

。たとえば、最初の行では、line.index(None)は、そのリスト内でNoneが最初に出現するため、常に2を返します。

代わりにこれを試してみてください:

def treat_missing_values(table): 
     for line in table: 
      for i in range(len(line)): 
       if line[i] == None: 
        if i != 0: 
         line[i] = line[i - 1] 
        else: 
         #This line deals with your other problem: What if your FIRST value is None? 
         line[i] = 0 #Some default value here 
     return table 
+0

おっと!そこに迷子の変数を残しました。今修正されました。私は列挙のために 'value'を' i' –

3

をあなたはPythonで割り当てを行うと、あなたは単にメモリ内のオブジェクトの参照を作成しています。値を使用してリスト内のオブジェクトを設定することはできません。

希望することを行うには、適切なインデックスのリストに直接設定する必要があります。

前述のように、内側のリストのいずれかが最初の値としてNoneを持つ場合、アルゴリズムは機能しません。

だから、あなたはこのようにそれを行うことができます。

t = [[1, 3, None, 5, None], [2, None, None, 3, 1], [4, None, 2, 1, None]] 
def treat_missing_values(table, default_value): 
    last_value = default_value 
    for line in table: 
     for index in xrange(len(line)): 
      if line[index] is None: 
       line[index] = last_value 
      else: 
       last_value = line[index] 
    return table 

print treat_missing_values(t, 0) 
4

これは私がそれを行うだろうか、おそらくです:

>>> def treat_missing_values(table): 
...  for line in table: 
...   prev = None 
...   for i, value in enumerate(line): 
...    if value is None: 
...     line[i] = prev 
...    else: 
...     prev = value 
...  return table 
... 
>>> treat_missing_values([[1, 3, None, 5, None], [2, None, None, 3, 1], [4, None, 2, 1, None]]) 
[[1, 3, 3, 5, 5], [2, 2, 2, 3, 1], [4, 4, 2, 1, 1]] 
>>> treat_missing_values([[None, 3, None, 5, None], [2, None, None, 3, 1], [4, None, 2, 1, None]]) 
[[None, 3, 3, 5, 5], [2, 2, 2, 3, 1], [4, 4, 2, 1, 1]] 
+0

+1に変更しました。この場合は本当に巧妙です。 –

+1

私は入力を変更して返すのが好きだとは言えません。 – Malvolio

+1

@Malvolio、私は同意します。しかし、私はその質問によって確立された入出力の規約に固執することを決めた。 – senderle

3

値からインデックスを見上げについての事は動作しないことリストがNoneで始まる場合、または重複する値がある場合これを試してみてください:

def treat(v): 
    p = None 
    r = [] 
    for n in v: 
    p = p if n == None else n 
    r.append(p) 
    return r 

def treat_missing_values(table): 
    return [ treat(v) for v in table ] 

t = [[1, 3, None, 5, None], [2, None, None, 3, 1], [4, None, 2, 1, None]] 
print treat_missing_values(t) 

これはあなたの宿題ではありません。

EDITあなたがそこにファンをFPすべてのための機能バージョン:

def treat(l): 
    def e(first, remainder): 
    return [ first ] + ([] if len(remainder) == 0 else e(first if remainder[0] == None else remainder[0], remainder[1:])) 
    return l if len(l) == 0 else e(l[0], l[1:]) 
+2

+1「これはあなたの宿題ではないよ、おい」 – senderle

+0

笑。いいえ、宿題はありません。私はあなたが1つではなく2つの機能を持っているのが好きです。非常にきれいな。それがクラスの一部であるときに、このようなコードを構造化しますか? – Randomtheories

+0

それは(学校)クラスの一部であるとき、私はこのようなコードを構造化するでしょうか?なおさら!人々が読むことができるようにコードをきれいに書く。コンピュータは実際に気にしません。学術用コード*のみが存在する*読まれる。実際には、コードを読んでいる人があなたがしようとしていることを理解している限り、それは働く必要はありません。 – Malvolio

1

私は最新の有効な値を追跡するために、グローバル変数を使用すると思います。そして、繰り返しのためにmap()を使用します。

t = [[1, 3, None, 5, None], [2, None, None, 3, 1], [4, None, 2, 1, None]] 

prev = 0 
def vIfNone(x): 
    global prev 
    if x: 
     prev = x 
    else: 
     x = prev 
    return x 

print map(lambda line: map(vIfNone, line), t) 

EDIT: Malvolio、ここに。あなたの答えに書いて申し訳ありませんが、コメントで修正するにはあまりにも多くの間違いがありました。

  1. if x:は、すべての偽値(特に0と空の文字列)で失敗します。
  2. グローバル値の変更可は、です。これらはスレッドセーフではなく、他の特有の動作を生成します(この場合、リストがNoneで始まる場合、コードによって処理された最後の値に設定されます)。
  3. xの書き換えは不要; prevは常に正しい値を持ちます。一般的に
  4. 、このようなものは、ネーミングおよびので

のスコーピングのためのために、関数でラップする必要があります。

def treat(n): 
    prev = [ None ] 
    def vIfNone(x): 
     if x is not None: 
      prev[0] = x 
     return prev[0] 
    return map(vIfNone, n) 

は(閉じ変数として前の奇妙な使用に注意してくださいそれtreatの呼び出しごとにローカルになり、同じtreat呼び出しからvIfNoneのすべての呼び出しでグローバルになります。暗くておそらくPythonの理由がわからない場合は、配列でなければなりません)

+0

良い編集、Malvolio。あなたの修正版は私よりはるかに優れています。 1つの変更: "!= None"の代わりに "is not None"を使ってxを比較してください。ありがとう! –

+1

@Malvolio、それほど暗くて邪魔にならない。 Pythonは、関数内のどこにでも変数名を再バインドしようとすると、その変数名が関数にとってローカルであると仮定することによって、ローカル変数とグローバル変数を区別します。 Python 2では、スコープ内の変数を変更するには、実行したようにするか、グローバルを使用する必要があります。 Python 3では 'nonlocal'キーワードが追加されているので、Python 3では' prev = None'を、 'vIfNone'、' nonlocal prev'の定義の先頭に置くことができます。 – senderle

+0

@sendle - 少なくとも、ローカル変数を宣言しないというPythonの実験が失敗したことを確かに証明するという意味で、暗くはありませんが、それは邪魔です。 'global'と' nonlocal'の間には、とにかく膨大な量の変数を宣言しなければなりません。また、間違った変数に割り当てるという問題があります。少なくとも、宣言されていない変数はローカルであると仮定してPythonを誤っていました。対照的に、Javascriptは、宣言されていない変数がグローバルであるという恐ろしい誤った仮定をしています! – Malvolio