我有一个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))
答案 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])