2012-01-25 2 views
1

Я хочу заменить отсутствующие значения (None) на последнее предыдущее известное значение. Это мой код. Но это не сработает. Любые предложения для лучшего алгоритма?Подстановка недостающих значений в 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

Это потому, что метод index возвращает первое вхождение аргумента вы передаете к нему. В первой строке, например, line.index (None) всегда будет возвращать 2, потому что это первое появление None в этом списке.

Попробуйте вместо этого:

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

Упс! оставил там блуждающую переменную. Теперь это исправлено. Я изменил 'значение' на' i' –

3

Когда вы делаете задание в питона, вы просто создать ссылку на объект в памяти. Вы не можете использовать значение для установки объекта в списке, потому что вы фактически делаете ссылку на значение другим объектом в памяти.

Чтобы сделать то, что вы хотите, вам нужно установить прямо в списке по правому указателю.

Как указано, ваш алгоритм не будет работать, если один из внутренних списков имеет 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

@ Малволио, согласен. Но я решил придерживаться принципа ввода/вывода, установленного в вопросе. – 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

lol. Нет, не домашнее задание. Мне нравится, что у вас есть две функции вместо одной. Очень чистый. Вы бы также структурировали код, как это, когда он является частью класса? – 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. Общими глобальными значениями являются bad. Они не являются потокобезопасными и производят другие своеобразные поведения (в этом случае, если список начинается с 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 и глобальным по всем вызовам vIfNone из того же самого вызова treat, что вам нужно. Для темных и, вероятно, тревожных причин Python я не понимаю, это должен быть массив.)

+0

Хорошие правки, Malvolio. Ваша измененная версия намного лучше моей. Одно изменение: сравните x, используя «is not None» вместо «! = None». Благодаря! –

+1

@ Малволио, это не так темно и тревожно. Python частично разделяет локальные и глобальные переменные, предполагая, что если вы попытаетесь восстановить имя переменной в любом месте функции, это имя переменной является локальным для этой функции. В Python 2 изменение переменной в области содержимого требует, чтобы вы выполняли то же, что и вы, или использовали глобальный. Python 3 добавляет ключевое слово 'nonlocal', поэтому в Python 3 вы можете сделать' prev = None' и в верхней части определения 'vIfNone',' nonlocal prev'. – senderle

+0

@senderle - ну, он не темный, но он тревожит, по крайней мере, в том смысле, что он окончательно устанавливает, что эксперимент Python, не объявляющий локальные переменные, потерпел неудачу. Между 'global' и' nonlocal' должна быть объявлена ​​огромная доля переменных, * и * у вас все еще есть проблема присвоения ошибочно введенных переменных. По крайней мере, Python допустил ошибку, предположив, что необъявленные переменные являются локальными; Javascript, напротив, делает ужасно неправильное предположение о том, что необъявленные переменные являются глобальными! – Malvolio

Смежные вопросы