2011-02-06 138 views
0

我正在考虑写一个函数来规范化一些数据。一个简单的方法是修改通过,嵌套字典/列表

def normalize(l, aggregate=sum, norm_by=operator.truediv): 
    aggregated=aggregate(l) 
    for i in range(len(l)): 
     l[i]=norm_by(l[i], aggregated) 

l=[1,2,3,4] 
normalize(l) 
l -> [0.1, 0.2, 0.3, 0.4] 

然而,对于嵌套列表和类型的字典,我想内指数正常化在这个行不通的。我的意思是我想得到

l=[[1,100],[2,100],[3,100],[4,100]] 
normalize(l, ??) 
l -> [[0.1,100],[0.2,100],[0.3,100],[0.4,100]] 

任何想法如何我可以实现这样的标准化函数?

也许这将是疯狂的凉爽写

normalize(l[...][0]) 

是否有可能使这项工作?还是其他想法?

也不仅列表,但也可以嵌套字典。嗯...

编辑: 我刚刚发现,numpy提供了这样的语法(但列表)。任何人都知道我将如何自己实施省略技巧?

+0

任何重要原因,使就地操作而不是创建新对象?它可能会稍微慢一点,但从长远来看,它是值得的。 – tokland 2011-02-06 22:06:51

回答

0

使用此:

zip(normalize(zip(*l)[0]), zip(*l)[1]) 

有一个(通常不重要)副作用:内部列表被转化为元组。但是,这可以通过[list(el) for el in zip(normalize(zip(*l)[0]), zip(*l)[1])]进行更正。

如果你有一个字典,我想它会看起来像{'a': 1, 'b': 2},需要正常化的值。您可以通过使用l.items()使用上述伎俩:

dict(zip(normalize(zip(*l.items())[0]), zip(*l.items())[1])) 

编辑:

你可以做这样的事情:

def normalize(l, aggregate=sum, norm_by=operator.truediv, key=None): 
    aggregated=aggregate(l) 
    for i in range(len(l)): 
     if key is not None: 
      l[i][key] = norm_by(l[i][key], aggregated) 
     else: 
      l[i]=norm_by(l[i], aggregated) 

,并调用函数

normalize(l, key=0) 
+0

我可能更喜欢扩展标准化函数的方式,以便长期运行更加舒适:)并且不会变换太多,因为序列可能非常大。或者我想到的省略号语法可能就像normalize(l,further_access = ?? [0]) – Gerenuk 2011-02-06 20:33:04

4

我不认为有任何改变e normalize()功能是必要的。要处理嵌套列表,您只需提供正确的aggregate()norm_by()函数来处理这种情况。

l = [[1, 100], [2, 100], [3, 100], [4, 100]] 
def aggregator(l): 
    return sum(item[0] for item in l) 

def normalizer(item , aggregated): 
    # mutating the inner list 
    item[0] = operator.truediv(item[0], aggregated) 
    return item 

normalize(l, aggregate = aggregator, norm_by = normalizer) 
# l -> [[0.1, 100], [0.2, 100], [0.3, 100], [0.4, 100]] 
0

我建议创建新对象而不是就地修改。假设在迭代的每个元素可以是不同的(如果不是,你可以把它更有效地通过选择合并功能或更早):

def normalize(input, index=None, aggregate=sum, norm_by=operator.truediv): 
    aggregated = aggregate(input) 
    for item in input: 
     if isinstance(item, list): 
      yield item[:index] + [norm_by(item[index], aggregated)] + item[index+1:] 
     elsif isinstance(item, dict): 
      yield dict(d, **{index: norm_by(item[index], aggregated)}) 
     else: 
      yield norm_by(item, aggregated) 

的情况下使用:

normalize([1, 2, 3]) 
normalize([(1, 2), (3, 4)], 0) 
normalize([{"a": 1, "b": 2}, {"a": 3, "b": 4}], "a")