Python 基于索引获取数组特定行的中值
我有两个长度相同的数组,一个包含索引,另一个包含其相应的值,即一个索引可以有多个值:Python 基于索引获取数组特定行的中值,python,arrays,numpy,Python,Arrays,Numpy,我有两个长度相同的数组,一个包含索引,另一个包含其相应的值,即一个索引可以有多个值: idx = [0,0,0,1,1,1,2,2,2,3,3,3,4,4,5,5...] values = [1.2,3.1,3.1,3.1,3.3,1.2,3.3,4.1,5.4...] 我想返回一个数组,其中包含唯一索引以及具有相同idx值的对象的中值 e、 g 我的暴力方法是: for idxi in np.arange(np.max(idx)): mask = (idxi == idx)
idx = [0,0,0,1,1,1,2,2,2,3,3,3,4,4,5,5...]
values = [1.2,3.1,3.1,3.1,3.3,1.2,3.3,4.1,5.4...]
我想返回一个数组,其中包含唯一索引以及具有相同idx值的对象的中值
e、 g
我的暴力方法是:
for idxi in np.arange(np.max(idx)):
mask = (idxi == idx)
medians = np.median(values[mask])
result.append([idxi,medians])
不幸的是,这远远不能满足我的需要,而且在任何情况下都非常难看。对于idx数组,您可以使用
numpy.unique
获取唯一项,要从另一个数组中获取相应的值,我们可以使用numpy.diff
和numpy.where
获取项发生变化的索引。使用这些索引,我们可以使用numpy.array\u split
拆分值数组,然后对其项应用np.mean
:
>>> idx = np.array([0,0,0,1,1,1,2,2,2,3,3,3,4,4,5,5])
>>> values = np.array([1.2,3.1,3.1,3.1,3.3,1.2,3.3,4.1,5.4] + [1]*7)
>>> indices = np.where(np.diff(idx) != 0)[0] + 1
>>> map(np.mean, np.array_split(values, indices))
[2.4666666666666668, 2.5333333333333337, 4.2666666666666666, 1.0, 1.0, 1.0]
>>> np.unique(idx)
array([0, 1, 2, 3, 4, 5])
>>> np.dstack((_, __))[0]
array([[ 0. , 2.46666667],
[ 1. , 2.53333333],
[ 2. , 4.26666667],
[ 3. , 1. ],
[ 4. , 1. ],
[ 5. , 1. ]])
如果您不介意依赖于
scipy
,该函数可以做到这一点。这里有一个例子
首先设置示例数据:
In [570]: import numpy as np
In [571]: idx = np.array([0,0,0,1,1,1,2,2,2,3,3,3,4,4,5,5])
In [572]: values = np.array([1.2,3.1,3.1,3.1,3.3,1.2,3.3,4.1,5.4,6,6,6.2,6,7,7.2,7.2])
在idx
中获取唯一的“标签”。(如果您已经知道最大值是,比如说,N
,并且您知道使用了从0到N
的所有整数,那么您可以使用uniq=range(N+1)
。)
使用labeled\u comprehension
计算每个标记组的中位数:
In [575]: from scipy.ndimage import labeled_comprehension
In [576]: medians = labeled_comprehension(values, idx, uniq, np.median, np.float64, None)
In [577]: medians
Out[577]: array([ 3.1, 3.1, 4.1, 6. , 6.5, 7.2])
如果您不介意依赖,另一个选项是使用
pandas.DataFrame
类的groupby
函数
设置数据帧:
In [609]: import pandas as pd
In [610]: df = pd.DataFrame(dict(labels=idx, values=values))
In [611]: df
Out[611]:
labels values
0 0 1.2
1 0 3.1
2 0 3.1
3 1 3.1
4 1 3.3
5 1 1.2
6 2 3.3
7 2 4.1
8 2 5.4
9 3 6.0
10 3 6.0
11 3 6.2
12 4 6.0
13 4 7.0
14 5 7.2
15 5 7.2
使用groupby
对使用labels
列的数据进行分组,然后计算组的中间值:
In [612]: result = df.groupby('labels').median()
In [613]: result
Out[613]:
values
labels
0 3.1
1 3.1
2 4.1
3 6.0
4 6.5
5 7.2
免责声明:我没有在大型阵列上尝试过这两种建议,因此我不知道它们的性能将如何与您的暴力解决方案或@Ashwini的答案进行比较。只有当idx值按顺序排列并正确分组(即[0,0,0,1,1,1…]而不是[0,1,2,0,1…])时,这才有效?这是否适用于idx值的任何排序?对不起,我的示例太具体了。@Griff如果它们不是顺序的,那么我们可以先对它们进行排序,然后对相应的值进行排序(使用
numpy.argsort
)。这将使它变得复杂,虽然我们在纯Python中仍然可以在O(N)
时间中这样做,但是过多的for循环可能会减慢速度。Minor:media
是groupby对象的一种方法,因此df.groupby(“标签”).media()
也会起作用。
In [609]: import pandas as pd
In [610]: df = pd.DataFrame(dict(labels=idx, values=values))
In [611]: df
Out[611]:
labels values
0 0 1.2
1 0 3.1
2 0 3.1
3 1 3.1
4 1 3.3
5 1 1.2
6 2 3.3
7 2 4.1
8 2 5.4
9 3 6.0
10 3 6.0
11 3 6.2
12 4 6.0
13 4 7.0
14 5 7.2
15 5 7.2
In [612]: result = df.groupby('labels').median()
In [613]: result
Out[613]:
values
labels
0 3.1
1 3.1
2 4.1
3 6.0
4 6.5
5 7.2