Numpy slicing allows you to input a list of indices to an array so that you can slice to the exact values you want.
For example:
import numpy as np
a = np.random.randn(10)
a[[2,4,6,8]]
This will return the 2nd, 4th, 6th, and 8th array elements (keeping in mind that python indices start from 0). So, if you want every 2nd element starting from an index x, you can simply populate a list with those elements and then feed that list into the array to get the elements you want, e.g:
idx = list(range(2,10,2))
a[idx]
This again returns the desired elements (index 2,4,6,8).
Answer from enumaris on Stack OverflowNumpy slicing allows you to input a list of indices to an array so that you can slice to the exact values you want.
For example:
import numpy as np
a = np.random.randn(10)
a[[2,4,6,8]]
This will return the 2nd, 4th, 6th, and 8th array elements (keeping in mind that python indices start from 0). So, if you want every 2nd element starting from an index x, you can simply populate a list with those elements and then feed that list into the array to get the elements you want, e.g:
idx = list(range(2,10,2))
a[idx]
This again returns the desired elements (index 2,4,6,8).
Your x is an array of length 20
x = np.arange(0,20)
Returns
x [ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19]
Access every nth(even indices here) element ignoring first two and last two indices in the array x by
print(x[2:len(x)-1:2])
Returns
[2 4 6 8]
And for the rest in similar fashion,
print(x[5:len(x)-1:5])
print(x[4:len(x)-1:4])
Returns
[ 5 10 15]
[ 4 8 12 16]
Range of indexes
python - Define range for index for lists in for loops - Stack Overflow
How to get the index range of a list that the values satisfy some criterion in Python? - Stack Overflow
arrays - Python: how to find a range of indexes from small to large? - Stack Overflow
Videos
for i in range(15):
print i #will print out 0..14
for i in range(1, 15):
print i # will print out 1..14
for i in range (a, b, s):
print i # will print a..b-1 counting by s. interestingly if while counting by the step 's' you exceed b, it will stop at the last 'reachable' number, example
for i in range(1, 10, 3):
print i
> 1
> 4
> 7
List Splicing:
a = "hello" # there are 5 characters, so the characters are accessible on indexes 0..4
a[1] = 'e'
a[1:2] = 'e' # because the number after the colon is not reached.
a[x:y] = all characters starting from the character AT index 'x' and ending at the character which is before 'y'
a[x:] = all characters starting from x and to the end of the string
In the future, if you ever wonder what the behavior of python is like, you can try it out in the python shell. just type python in the terminal and you can enter any lines you want (though this is mostly convenient for one-liners rather than scripts).
The best way to clarify such doubts is to play with the REPL:
>>> range(10)
range(0, 10)
>>> list(range(10))
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> x = list(range(10))
>>> x[:3]
[0, 1, 2]
>>> x[:1]
[0]
>>> x[1:10]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
So I was practicing list today, and I'm a bit confused.
Here's the little code I did:
samplelist = [0, "lily", "kiki", 78, "papapa"]
print(samplelist[0:4])
The output is like this:
[0, 'lily', 'kiki', 78]
I thought since list is index based(?), it would show everything including "papapa". I tried putting 5 instead of 4, and it showed everything. Why?
If you really want to use manual indexing, then dont use enumerate() and just create a range() (or xrange() if Python 2.x) of the right size, ie:
for i in xrange(len(a) - 2):
# code here
Now you don't have to manually take care of indexes at all - if you want to iterate over (a[x], a[x+1]) pairs all you need is zip():
for x, y in zip(a, a[1:]):
if abs(x - y) < min:
min = abs(x - y)
zip(seq1, seq2) will build a list of (seq1[i], seq2[i]) tuples (stopping when the smallest sequence or iterator is exhausted). Using a[1:] as the second sequence, we will have a list of (a[i], a[i+1]) tuples. Then we use tuple unpacking to assign each of the tuple's values to x and y.
But you can also just use the builtin min(iterable) function instead:
min(abs(x - y) for x, y in zip(a, a[1:]))
which is the pythonic way to get the smallest value of any sequence or iterable.
Note that with Python 2.x, if your real list is actually way bigger, you'll benefit from using itertools.izip instead of zip
As as side note, using min (actually using any builtin name) as a variable name is possibly not a good idea as it shadows the builtin in the current namespace. If you get a TypeError: 'int' object is not callable message trying this code you'll know why...
You can pass a slice of a with the specified start and stop indices to enumerate:
for i, x in enumerate(a[:size-1]):
...
i will run from 0 to size-2
On a side note, comments in Python start with # and not //
You can achieve the same results by using min on a generator expression created from the zip of a and its advanced slice:
minimum = min(abs(i - j) for i, j in zip(a, a[1:]))
Also, be careful to not use the name min as this already shadows the builtin min. Something you obviously don't want.
a = [12,11,5,7,2,21,32,13,6,42,1,8,9,0,32,38]
indices = [idx for idx,val in enumerate(a) if val < 10]
This creates a list of indices:
[2, 3, 4, 8, 10, 11, 12, 13]
I would recommend keeping it that way for easy parsing, but you can also turn it into ranges as follows:
ranges = [[]]
for val in indices:
if not ranges[-1] or ranges[-1][-1] == val-1:
ranges[-1].append(val)
else:
ranges.append([val])
This creates a list of ranges:
[[2, 3, 4], [8], [10, 11, 12, 13]]
Now to take out the middle:
ranges = [[item[0],item[-1]] if len(item) > 1 else item for item in ranges]
Result:
[[2, 4], [8], [10, 13]]
You can have your function take a function as an argument to use as the predicate for building your intervals:
def indexscope(dlist, predicate):
scope = []
start = end = -1
for i, v in enumerate(dlist):
if predicate(v):
if start == -1:
start = end = i
continue
if end + 1 == i:
end = i
else:
scope.append([start] if start == end else [start, end])
start = end = i
if start != -1:
scope.append([start] if start == end else [start, end])
return scope
a = [12,11,5,7,2,21,32,13,6,42,1,8,9,0,32,38]
def less_than_10(n):
return n < 10
print(indexscope(a, less_than_10))
print(indexscope(a, lambda x: x > 20))
[[2, 4], [8], [10, 13]]
[[5, 6], [9], [14, 15]]
with scipy:
import numpy as np
import scipy.ndimage as nd
def passing_ranges(a, predicate):
return nd.find_objects(nd.label(predicate(a))[0])
The results are returned as slice objects, but that is to your advantage because you can use them to against your original np array:
small_a = [12,11,5,7,2,21,32,13,6,42,1,8,9,0,32,38]
small_np_array = np.array(small_a)
valid_ranges = passing_ranges(small_np_array, lambda n: n < 10)
for r in valid_ranges:
print(r[0], small_np_array[r])
slice(2, 5, None) [5 7 2]
slice(8, 9, None) [6]
slice(10, 14, None) [1 8 9 0]
benchmarks
large_a = [12,11,5,7,2,21,32,13,6,42,1,8,9,0,32,38]*1000000
large_np_array = np.array(large_a)
%timeit passing_ranges(large_np_array, lambda x: x < 10)
1 loops, best of 3: 1.2 s per loop
%timeit indexscope(large_a, lambda n: n < 10)
1 loops, best of 3: 6.99 s per loop
Here is your answer, I even inline the predicate to remove a function call:
from itertools import groupby, count
def xibinke(a):
l = [idx for idx,value in enumerate(a) if value<10]
return [list(g) for _,g in groupby(l,key=lambda n,c=count():n-next(c))]
%timeit xibinke(large_a)
1 loops, best of 3: 14.6 s per loop
What condition are you looking to satisfy?
import pandas as pd
df=pd.DataFrame([['This is also a interesting topic',2],['<body> the valley of flowers ...',1],['found in the hilly terrain',5],
['we must preserve it </body>',6]],columns=['description','count'])
print(df)
print(len(df[df['count'] != 2].index))
Here, df['count'] != 2 subsets the df, and len(df.index) returns the length of the index.
Updated; note that I used str.contains(), rather than explicitly looking for starting or ending strings.
df2 = df[(df.description.str.contains('<body>') | (df.description.str.contains('</body>')))]
print(df2)
print(len(df2.index))
help from: Check if string is in a pandas dataframe
You can also find the index of start and end row then add the rows in between them to get all contents in between
start_index = df[df['description'].str.contains("<body>")==True].index[0]
end_index = df[df['description'].str.contains("</body>")==True].index[0]
print(df["description"][start_index:end_index+1].sum())