计算所选列的行平均值

时间:2016-06-13 06:01:26

标签: python csv numpy

我有一个csv文件:

#col1 #col2 ... #col253
33,    123, ...    99
19,    409, ...    24
34,    239, ...    60
...    ...  ...    ..

和一个字典,其值存储所选列的开始和结束索引:

d = {
    'win': [(11, 55), (194, 233)],
    'lose': [(72, 111), (133, 172)],
    'neut': [(0, 10), (51, 71), (112, 132), (173, 193)]
    }

我的目标是计算字典中某个键的所有选定列的每行平均值。

例如,对于第一行的'win'块,选择11, 12, ...55, 194, 195,...233列并计算平均值。

我现在使用的是什么:

x = np.loadtxt('filename.csv', delimiter=',')
for line in x:
    selected = [line[start:end + 1] for (start, end) in d['win']]
    ...

selected将为[array([39, 12, 94,...]), array([3, 4, ...])],无法传递给np.mean()

所以列表中的数组应该合并为一个,我不知道如何优雅地做,或者迭代地添加所有数字,然后取平均值,我认为这很难看。

编辑:

一种丑陋的方法可能是:

average = sum(map(sum, selected)) / sum(map(len, selected))

2 个答案:

答案 0 :(得分:2)

Numpy数组支持rich indexing,因此可以通过对所有行进行切片并传递列表来进行选择来实现。

要分别计算每一行,您可以将计算平均值的axis(或轴)作为参数传递给mean()

columns = np.hstack(tuple(np.arange(a, b + 1) for a, b in d['win']))
row_means = x[:, columns].mean(axis=1)

答案 1 :(得分:1)

您可以使用this other solution以矢量化方式创建涵盖所有 interval-ed 范围的列数组。然后,使用这些列索引输入数组x的列,并计算沿第二轴(axis=1)的平均值。

让我列出向量化函数,以便在此处再次创建此类 interval-ed 范围的数组 -

def using_ones_cumsum_v2(array1, array2):
    lens = array2 - array1
    id_arr = np.ones(lens.sum(),dtype=array1.dtype)
    id_arr[lens[:-1].cumsum()] = np.diff(array1) - lens[:-1]+1
    id_arr[0] = array1[0]
    return id_arr.cumsum()

有了它,我们将获得win键的平均值,如此 -

d_win = np.array(d['win'])
out_win = x[:,using_ones_cumsum_v2(d_win[:,0],d_win[:,1]+1)].mean(1)

示例运行以演示using_ones_cumsum_v2用于创建区间编辑范围的用法 -

In [24]: d = {
    ...:     'win': [(1, 3), (5, 8)],
    ...:     'lose': [(2, 5), (7, 8)],
    ...:     'neut': [(0, 1), (4, 7), (8, 9)]
    ...:     }

In [25]: d_win = np.array(d['win'])

In [26]: d_win
Out[26]: 
array([[1, 3],
       [5, 8]])

In [27]: using_ones_cumsum_v2(d_win[:,0],d_win[:,1]+1)
Out[27]: array([1, 2, 3, 5, 6, 7, 8])