It looks like you just need a basic integer array indexing:
filter_indices = [1,3,5]
np.array([11,13,155,22,0xff,32,56,88])[filter_indices]
Answer from Joran Beasley on Stack OverflowIt looks like you just need a basic integer array indexing:
filter_indices = [1,3,5]
np.array([11,13,155,22,0xff,32,56,88])[filter_indices]
numpy.take can be useful and works well for multimensional arrays.
import numpy as np
filter_indices = [1, 2]
array = np.array([[1, 2, 3, 4, 5],
[10, 20, 30, 40, 50],
[100, 200, 300, 400, 500]])
axis = 0
print(np.take(array, filter_indices, axis))
# [[ 10 20 30 40 50]
# [100 200 300 400 500]]
axis = 1
print(np.take(array, filter_indices, axis))
# [[ 2 3]
# [ 20 30]
# [200 300]]
As Toan suggests, a simple hack would be to just select the rows first, and then select the columns over that.
>>> a[[0,1,3], :] # Returns the rows you want
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[12, 13, 14, 15]])
>>> a[[0,1,3], :][:, [0,2]] # Selects the columns you want as well
array([[ 0, 2],
[ 4, 6],
[12, 14]])
[Edit] The built-in method: np.ix_
I recently discovered that numpy gives you an in-built one-liner to doing exactly what @Jaime suggested, but without having to use broadcasting syntax (which suffers from lack of readability). From the docs:
Using ix_ one can quickly construct index arrays that will index the cross product.
a[np.ix_([1,3],[2,5])]returns the array[[a[1,2] a[1,5]], [a[3,2] a[3,5]]].
So you use it like this:
>>> a = np.arange(20).reshape((5,4))
>>> a[np.ix_([0,1,3], [0,2])]
array([[ 0, 2],
[ 4, 6],
[12, 14]])
And the way it works is that it takes care of aligning arrays the way Jaime suggested, so that broadcasting happens properly:
>>> np.ix_([0,1,3], [0,2])
(array([[0],
[1],
[3]]), array([[0, 2]]))
Also, as MikeC says in a comment, np.ix_ has the advantage of returning a view, which my first (pre-edit) answer did not. This means you can now assign to the indexed array:
>>> a[np.ix_([0,1,3], [0,2])] = -1
>>> a
array([[-1, 1, -1, 3],
[-1, 5, -1, 7],
[ 8, 9, 10, 11],
[-1, 13, -1, 15],
[16, 17, 18, 19]])
Fancy indexing requires you to provide all indices for each dimension. You are providing 3 indices for the first one, and only 2 for the second one, hence the error. You want to do something like this:
>>> a[[[0, 0], [1, 1], [3, 3]], [[0,2], [0,2], [0, 2]]]
array([[ 0, 2],
[ 4, 6],
[12, 14]])
That is of course a pain to write, so you can let broadcasting help you:
>>> a[[[0], [1], [3]], [0, 2]]
array([[ 0, 2],
[ 4, 6],
[12, 14]])
This is much simpler to do if you index with arrays, not lists:
>>> row_idx = np.array([0, 1, 3])
>>> col_idx = np.array([0, 2])
>>> a[row_idx[:, None], col_idx]
array([[ 0, 2],
[ 4, 6],
[12, 14]])
This is what numpy.delete does. (It doesn't modify the input array, so you don't have to worry about that.)
In [4]: np.delete(x, exclude)
Out[4]: array([ 0, 20, 40, 60])
np.delete does various things depending what you give it, but in a case like this it uses a mask like:
In [604]: mask = np.ones(x.shape, bool)
In [605]: mask[exclude] = False
In [606]: mask
Out[606]: array([ True, False, True, False, True, False, True], dtype=bool)
In [607]: x[mask]
Out[607]: array([ 0, 20, 40, 60])
If you've got a boolean array you can do direct selection based on that like so:
>>> a = np.array([True, True, True, False, False])
>>> b = np.array([1,2,3,4,5])
>>> b[a]
array([1, 2, 3])
To go along with your initial example you could do the following:
>>> a = np.array([[1,2,3], [4,5,6], [7,8,9]])
>>> b = np.array([[False,True,False],[True,False,False],[False,False,True]])
>>> a[b]
array([2, 4, 9])
You can also add in an arange and do direct selection on that, though depending on how you're generating your boolean array and what your code looks like YMMV.
>>> a = np.array([[1,2,3], [4,5,6], [7,8,9]])
>>> a[np.arange(len(a)), [1,0,2]]
array([2, 4, 9])
You can do something like this:
In [7]: a = np.array([[1, 2, 3],
...: [4, 5, 6],
...: [7, 8, 9]])
In [8]: lst = [1, 0, 2]
In [9]: a[np.arange(len(a)), lst]
Out[9]: array([2, 4, 9])
More on indexing multi-dimensional arrays: http://docs.scipy.org/doc/numpy/user/basics.indexing.html#indexing-multi-dimensional-arrays
There are some higher-level functions, but let's see how to do it using just the simplest stuff in the library, because you're going to need those simple functions every day.
>>> matches = (I == 2)
>>> matches
array([False, False, True, False, False, True, False, False, False,
False, False, True, False, True, False], dtype=bool)
>>> indices = np.nonzero(matches)
>>> indices
(array([ 2, 5, 11, 13]),)
>>> xvals = X[indices]
>>> xvals
array([[ 3.6 , 2.01],
[ 3.9 , 7.02],
[ 4.5 , 7.55],
[ 4.7 , 0.33]])
The last step may look confusing. See Indexing in the tutorial for further information.
Once you understand how the == operator and nonzero work, look through the other functions in the same section as nonzero and you should find two shorter ways to do this.
If you would like to try pandas, it's really powerful in groupby data. Here's how you can achieve what you need:
In [34]: import numpy as np
In [35]: import pandas as pd
#I defined you X, I already
In [36]: X
Out[36]:
array([[ 3.4 , 9.13],
[ 3.5 , 3.43],
[ 3.6 , 2.01],
[ 3.7 , 6.11],
[ 3.8 , 4.95],
[ 3.9 , 7.02],
[ 4. , 4.41],
[ 4.1 , 0.23],
[ 4.2 , 0.99],
[ 4.3 , 1.02],
[ 4.4 , 5.61],
[ 4.5 , 7.55],
[ 4.6 , 8.1 ],
[ 4.7 , 0.33],
[ 4.8 , 0.8 ]])
In [37]: I
Out[37]: array([0, 1, 2, 0, 1, 2, 3, 0, 1, 0, 1, 2, 0, 2, 1], dtype=int64)
In [38]: dataframe=pd.DataFrame (data=X, index=I, columns=['X1','X2'])
In [39]: dataframe.index.name='I' #This is not necessary
In [40]: print dataframe
X1 X2
I
0 3.4 9.13
1 3.5 3.43
2 3.6 2.01
0 3.7 6.11
1 3.8 4.95
2 3.9 7.02
3 4.0 4.41
0 4.1 0.23
1 4.2 0.99
0 4.3 1.02
1 4.4 5.61
2 4.5 7.55
0 4.6 8.10
2 4.7 0.33
1 4.8 0.80
This defines a dataframe with I as index and X as data. Now if you need rows with I=2, you can do
In [42]: print dataframe.ix[2]
X1 X2
I
2 3.6 2.01
2 3.9 7.02
2 4.5 7.55
2 4.7 0.33
If you want to list all groups:
In [43]: for i, grouped_data in dataframe.groupby(level='I'): #without level=, you can group by a regular column like X1
....: print i
....: print grouped_data
....:
0
X1 X2
I
0 3.4 9.13
0 3.7 6.11
0 4.1 0.23
0 4.3 1.02
0 4.6 8.10
1
X1 X2
I
1 3.5 3.43
1 3.8 4.95
1 4.2 0.99
1 4.4 5.61
1 4.8 0.80
2
X1 X2
I
2 3.6 2.01
2 3.9 7.02
2 4.5 7.55
2 4.7 0.33
3
X1 X2
I
3 4 4.41
If you just want to see statistics of each group, you can do
In [47]: print dataframe.groupby(level='I').sum() #try other funcs like mean, var, .
X1 X2
I
0 20.1 24.59
1 20.7 15.78
2 16.7 16.91
3 4.0 4.41