0

好的,这是我的问题。我有一个由每个元素(浮点数)组成的N子列表组成的列表。M所以在一般形式中,它看起来像这样:

a_list = [b_list_1, b_list_2, ..., b_list_N]

和:

b_list_i = [c_float_1, c_float_2, ..., c_float_M]

对于此示例假设N=9 ; M=3,因此列表如下所示:

a = [[1.1, 0.5, 0.7], [0.3, 1.4, 0.2], [0.6, 0.2, 1.], [1.1, 0.5, 0.3], [0.2, 1.1, 0.8], [1.1, 0.5, 1.], [1.2, 0.3, 0.6], [0.6, 0.4, 0.9], [0.6, 0.2, 0.5]]

我需要遍历这个列表,识别那些与前两个浮点数相同的项目,其中第三个浮点数在存储之前应该被平均。这意味着我应该检查一个项目是否已经被识别为以前重复,所以我不会再次将它识别为一个新项目。

为了更清楚地理解我的意思,这是处理列表的输出a应该是这样的:

a_processed = [[1.1, 0.5, 0.67], [0.3, 1.4, 0.2], [0.6, 0.2, 0.75], [0.2, 1.1, 0.8], [1.2, 0.3, 0.6], [0.6, 0.4, 0.9]]

a[0]请注意,这个新列表中的第一项在 ( ,a[3]和)中被标识了三次a[5],因此它与第三个浮点平均值 ( (0.7+0.3+1.)/3. = 0.67) 一起存储。第二项未重复,a因此按原样存储。第三个项目在a(a[2]a[8]) 中找到了两次,并以第三个浮点数的平均值 ( (1.+0.5)/2.=0.75) 存储。新列表中的其余项目没有发现重复,a因此它们也被存储而没有修改。

因为我知道不建议在循环时更新/修改列表,所以我选择使用几个临时列表。这是我想出的代码:

import numpy as np

a = [[1.1, 0.5, 0.7], [0.3, 1.4, 0.2], [0.6, 0.2, 1.], [1.1, 0.5, 0.3],
     [0.2, 1.1, 0.8], [1.1, 0.5, 1.], [1.2, 0.3, 0.6], [0.6, 0.4, 0.9],
[0.6, 0.2, 0.5]]

# Final list.
a_processed = []

# Holds indexes of elements to skip.
skip_elem = []

# Loop through all items in a.
for indx, elem in enumerate(a):
    temp_average = []
    temp_average.append(elem)        
    # Only process if not found previously.
    if indx not in skip_elem:
        for indx2, elem2 in enumerate(a[(indx+1):]):
            if elem[0] == elem2[0] and elem[1] == elem2[1]:
                temp_average.append(elem2)
                skip_elem.append(indx2+indx+1)

        # Store 1st and 2nd floats and averaged 3rd float.
        a_processed.append([temp_average[0][0], temp_average[0][1],
                            round(np.mean([i[2] for i in temp_average]),2)])

此代码有效,但我想知道是否有更优雅/pythonic 的方式来执行此操作。它看起来太复杂了(我会说是Fortran式的)。

4

2 回答 2

4

我认为您当然可以通过使用defaultdict创建从每个子列表中的前两个元素到所有第三项的字典来使您的代码更简洁和更易于阅读:

from collections import defaultdict
nums = defaultdict(list)
for arr in a:
    key = tuple(arr[:2]) # make the first two floats the key
    nums[key].append( arr[2] ) # append the third float for the given key

a_processed = [[k[0], k[1], sum(vals)/len(vals)] for k, vals in nums.items()]

使用它,我得到与你相同的输出(尽管顺序不同):

[[0.2, 1.1, 0.8], [1.2, 0.3, 0.6], [0.3, 1.4, 0.2], [0.6, 0.4, 0.9], [1.1, 0.5, 0.6666666666666666], [0.6, 0.2, 0.75]]

如果顺序a_processed是一个问题,您可以使用OrderedDict@DSM 指出的 。

于 2013-10-24T15:56:56.337 回答
4

为了比较,这里是pandas方法。如果这真的是幕后的数据处理问题,那么您可以通过这种方式为自己节省大量时间。

>>> a
[[1.1, 0.5, 0.7], [0.3, 1.4, 0.2], [0.6, 0.2, 1.0], [1.1, 0.5, 0.3], [0.2, 1.1, 0.8], [1.1, 0.5, 1.0], [1.2, 0.3, 0.6], [0.6, 0.4, 0.9], [0.6, 0.2, 0.5]]
>>> df = pd.DataFrame(a)
>>> df.groupby([0,1]).mean()
                2
0   1            
0.2 1.1  0.800000
0.3 1.4  0.200000
0.6 0.2  0.750000
    0.4  0.900000
1.1 0.5  0.666667
1.2 0.3  0.600000

这个问题很常见,以至于它是单行的。您可以使用命名列、计算大量其他有用的统计信息、处理丢失的数据等。

于 2013-10-24T16:25:02.800 回答