1

我想用上一个已知值替换缺失值(无)。这是我的代码。但它不起作用。对更好的算法有什么建议吗?

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)
4

6 回答 6

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]]
于 2012-01-25T02:57:15.477 回答
3

当你在 python 中进行赋值时,你只是在内存中创建一个对象的引用。您不能使用 value 来设置列表中的对象,因为您实际上是在让 value 引用内存中的另一个对象。

要做你想做的,你需要直接在列表中设置正确的索引。

如前所述,如果其中一个内部列表将 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)
于 2012-01-25T02:54:46.463 回答
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:])   
于 2012-01-25T02:59:54.743 回答
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
于 2012-01-25T02:54:28.757 回答
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 )

编辑:马伏里奥,在这里。很抱歉写你的答案,但评论中有太多错误需要纠正。

  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 )

(请注意 prev 作为封闭变量的奇怪用法。它将是每次调用的本地变量treat,并且在同一调用中对 vIfNone 的所有调用都是全局的treat,这正是您所需要的。出于黑暗和可能令人不安的 Python 原因,我不明白,它必须是一个数组。)

于 2012-01-25T03:15:34.727 回答
0

编辑1

# 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)
于 2012-01-25T02:51:02.677 回答