在Python中替换缺失值

时间:2012-01-25 02:46:52

标签: python missing-data

我想用最后一个已知值替换缺失值(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)

5 个答案:

答案 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]]

答案 1 :(得分: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)

答案 2 :(得分: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)

最好不要做你的功课,伙计。

编辑所有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:])   

答案 3 :(得分: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 )

编辑: Malvolio,在这里。很抱歉写下你的答案,但在评论中纠正的错误太多了。

  1. if x:将失败所有虚假值(特别是0和空字符串)。
  2. 可变全局值错误。它们不是线程安全的并且产生其他特殊行为(在这种情况下,如果列表以None开头,则它被设置为您的代码碰巧处理的最后一个值。
  3. 重写x是不必要的; prev始终具有正确的价值。
  4. 一般来说,这样的事情应该包含在函数中,用于命名和用于作用域
  5. 所以:

    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的每次调用中是本地的,并且在来自同一{{1}的所有vIfNone调用中是全局的。调用,正是你需要的。对于黑暗和可能令人不安的Python原因,我不明白,它必须是一个数组。)

答案 4 :(得分: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)