Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 基于索引获取数组特定行的中值_Python_Arrays_Numpy - Fatal编程技术网

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