Подстановка отсутствующих значений в Python
Я хочу заменить отсутствующие значения (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 value in line:
if value == None:
value = line[line.index(value)-1]
return table
print treat_missing_values(t)
Ответы
Ответ 1
Скорее всего, я это сделаю:
>>> 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]]
Ответ 2
Когда вы выполняете задание в 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)
Ответ 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:])
Ответ 4
Это потому, что метод 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
Ответ 5
Я бы использовал глобальную переменную, чтобы отслеживать последнее действительное значение. И я использовал бы 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 )
РЕДАКТИРОВАТЬ: Мальволио, здесь. Извините, что писал в вашем ответе, но в комментарии было слишком много ошибок.
-
if x:
выйдет из строя для всех значений ложности (в частности, 0 и пустой строки).
- Изменчивые глобальные значения плохи. Они не являются потокобезопасными и производят другие своеобразные поведения (в этом случае, если список начинается с None, он устанавливается на последнее значение, которое было обработано вашим кодом.
- Повторная запись
x
не нужна; prev
всегда имеет правильное значение.
- В общем, такие вещи должны быть обернуты функциями, для именования и для определения области охвата.
Итак:
def treat(n):
prev = [ None ]
def vIfNone(x):
if x is not None:
prev[0] = x
return prev[0]
return map( vIfNone, n )
(Обратите внимание на странное использование prev как закрытой переменной. Оно будет локально для каждого вызова treat
и глобального для всех вызовов vIfNone из одного и того же вызова treat
, что вам нужно. вероятно, беспокоя причины Python, которые я не понимаю, это должен быть массив.)
Ответ 6
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)