Related
Say I have an array with longitudes, lonPorts
lonPort =np.loadtxt('LongPorts.txt',delimiter=',')
for example:
lonPort=[0,1,2,3,...]
And I want to repeat each element a different amount of times. How do I do this? This is what I tried:
Repeat =[5, 3, 2, 3,...]
lonPort1=[]
for i in range (0,len(lenDates)):
lonPort1[sum(Repeat[0:i])]=np.tile(lonPort[i],Repeat[i])
So the result would be:
lonPort1=[0,0,0,0,0,1,1,1,2,2,3,3,3,...]
The error I get is:
list assignment index out of range
How do I get rid of the error and make my array?
Thank you!
You can use np.repeat():
np.repeat(a, [5,3,2,3])
Example:
In [3]: a = np.array([0,1,2,3])
In [4]: np.repeat(a, [5,3,2,3])
Out[4]: array([0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 3])
Without relying on numpy, you can create a generator that will consume your items one by one, and repeat them the desired amount of time.
x = [0, 1, 2, 3]
repeat = [4, 3, 2, 1]
def repeat_items(x, repeat):
for item, r in zip(x, repeat):
while r > 0:
yield item
r -= 1
for value in repeat_items(x, repeat):
print(value, end=' ')
displays 0 0 0 0 1 1 1 2 2 3.
Providing a numpy-free solution for future readers that might want to use lists.
>>> lst = [0,1,2,3]
>>> repeat = [5, 3, 2, 3]
>>> [x for sub in ([x]*y for x,y in zip(lst, repeat)) for x in sub]
[0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 3]
If lst contains mutable objects, be aware of the pitfalls of sequence multiplication for sequences holding mutable elements.
I have the following array
a = [0,0,1,0,0,0,1,1,0,0,0,0,1,1,1,0,0,0,0,0,1]
I want to group every 3rd element and sum all of the elements within each group. So I can get a new array with a new size showing this sum
b = [1,0,2,0,3,0,1]
Any suggestions?
Simply, most pythonicly would be the following
b = [sum(a[i:i+3]) for i in range(0, len(a), 3)]
where your input array is a.
>>> a = [0,0,1,0,0,0,1,1,0,0,0,0,1,1,1,0,0,0,0,0,1]
>>> b = [sum(a[i:i+3]) for i in range(0, len(a), 3)]
>>> b
[1, 0, 2, 0, 3, 0, 1]
You can split in chunk and sum:
step = 3
[sum(a[i:i+step]) for i in range(0, len(a),step)]
[1, 0, 2, 0, 3, 0, 1]
If the length is not the multiple of step, last chunk might be smaller.
Maybe something like this:
a = [0,0,1,0,0,0,1,1,0,0,0,0,1,1,1,0,0,0,0,0,1]
b = []
for i in range(0,len(a),3):
b.append(sum(a[i:i+3]))
print b
Output:
[1, 0, 2, 0, 3, 0, 1]
Another option using groupby from itertools:
from itertools import groupby
[sum(v for _, v in g) for _, g in groupby(enumerate(a), key = lambda x: x[0]/3)]
# [1, 0, 2, 0, 3, 0, 1]
Or another way to use zip:
[sum(v) for v in zip(a[::3], a[1::3], a[2::3])]
# [1, 0, 2, 0, 3, 0, 1]
This question already has answers here:
python: most elegant way to intersperse a list with an element
(15 answers)
Closed 6 years ago.
I have a list like
[1, 2, 3, 4, 5]
and I want to add zeroes at odd indexes:
[1, 0, 2, 0, 3, 0, 4, 0, 5]
My first thought was to create a list with zeroes and replace them with the values from the original list.
listOfZeros = [0] * (2*len(list)-1)
j = 0
for i in range(0, len(listOfZeros)):
if (i%2 == 0):
listOfZeros[i] = h_temp[j]
j += 1
This actually works, but I do dislike for loops and adding another counter j. Isn't there a better way by using slicing?
You can use insert(). Looking at your output, assuming you are not counting index 0 as even.
a = [1,2,3,4,5]
for x in range(len(a)):
a.insert(2*x+1, 0)
one way is by using zip:
a = [1, 2, 3, 4, 5]
d = [x for t in zip (a, [0] * len(a)) for x in t][:-1]
When you use zip, you create list of tuples.
a = [1,2,3,4,5]
b = [0,0,0,0,0]
c = zip(a,b)
#zip (a,b) creates [(1,0),(2,0),(3,0),(4,0),(5,0)]
Then you loop over the set of tuples to arrange them into list:
d = [x for t in c for x in t] #creates [1,0,2,0,3,0,4,0,5,0]
and cut the last element (since you end with 5)
[x for t in c for x in t][:-1] #take out the last 0
#resulting in [1,0,2,0,3,0,4,0,5]
then you are done.
You can do it with a generator:
def zero_on_odd(mylist):
for i in mylist:
yield i
yield 0
a = [1, 2, 3]
with_zeros = list(zero_on_odd(a))[:-1]
If you want to go functional...
from itertools import chain, repeat
_list = [1,2,3,4,5]
list(chain(*zip(_list, repeat(0))))[:-1]
# [1, 0, 2, 0, 3, 0, 4, 0, 5]
If you want to be silly...
[int(i) for i in '0'.join(str(i) for i in _list)]
# still [1, 0, 2, 0, 3, 0, 4, 0, 5]
Or, if you want to be functional AND silly...
map(int, '0'.join(map(str, _list)))
# really, it's still [1, 0, 2, 0, 3, 0, 4, 0, 5]
# except in Python 3.X, there it's a map object...
But, you should probably opt for one of the custom generator solutions.
For the fun of it, here is an itertools solution:
from itertools import islice, chain
data = [1,2,3,4,5]
print list(islice(chain.from_iterable((x, 0) for x in data), 0, 2 * len(data)-1))
Giving:
[1, 0, 2, 0, 3, 0, 4, 0, 5]
Another zip way:
>>> li
[1, 2, 3, 4, 5]
>>> [e for t in zip(li,[0]*(len(li)-1)) for e in t]+[li[-1]]
[1, 0, 2, 0, 3, 0, 4, 0, 5]
You can also use range and slice assignment:
>>> li=[1,2,3,4,5]
>>> for i in range(1,len(li)+len(li)-1, 2): li[i:i]=[0]
...
>>> li
[1, 0, 2, 0, 3, 0, 4, 0, 5]
And, a list comprehension:
>>> [li[i/2] if not i%2 else 0 for i in range(len(li)*2-1)]
[1, 0, 2, 0, 3, 0, 4, 0, 5]
A hacky way:
>>> ls1 = [1, 2, 3, 4, 5]
>>> ls2 = []
>>> list(ls2.extend([n, 0]) for n in ls1)
[None, None, None, None, None]
>>> ls2
[1, 0, 2, 0, 3, 0, 4, 0, 5, 0]
I know that I can interleave two python lists with:
[elem for pair in zip(*lists) for elem in pair]
Now I need to interleave a list with a fixed element like:
list = [1, 2, 3, 4]
# 🐍 python magic 🐍
output = [1, 0, 2, 0, 3, 0, 4]
One really straightforward solution is:
[elem for x in list for elem in (x, 0)][:-1]
You can try the following itertools magic:
>>> from itertools import repeat, chain, izip
>>> l = [1, 2, 3, 4]
>>> list(chain.from_iterable(izip(l[:-1], repeat(0)))) + l[-1:]
[1, 0, 2, 0, 3, 0, 4]
from itertools import izip, repeat
start = [1, 2, 3, 4]
print [i for j in izip(start, repeat(0)) for i in j][:-1]
Python's sum function can be used on arbitrary datatypes that support addition by setting the start parameter appropriately. (see docs)
input = [1, 2, 3, 4]
fixed = 0
output = sum([[elem, fixed] for elem in input], [])[:-1] # to drop the last `fixed`
Or if you don't like the idea of using the addition operator with lists:
input = [1, 2, 3, 4]
fixed = 0
output = []
for elem in input:
output.extend([elem, fixed])
output = output[:-1]
>>> lst = [1, 2, 3, 4]
>>> newlst = [0]*((len(lst) * 2) - 1)
>>> newlst[::2] = lst
>>> newlst
[1, 0, 2, 0, 3, 0, 4]
It may not be a one-liner, but it works. Furthermore, my time tests seem to show that it's the fastest solution so far. In function form, this is:
def interzero(lst):
newlst = [0]*((len(lst) * 2) - 1)
newlst[::2] = lst
return newlst
You could use the reduce function of functools.
>>> from functools import reduce
>>> reduce(lambda x, y: x + [y, 0], [1,2,3,4], [])[:-1]
[1, 0, 2, 0, 3, 0, 4]
>>> from itertools import chain
>>> lst = [1, 2, 3, 4]
>>> list(chain(*zip(lst, [0]*(len(lst)-1)))) + [lst[-1]]
[1, 0, 2, 0, 3, 0, 4]
How can I repeat elements in place in an array in Python?
Or similarly, something more simple than this:
drange = [];
for i in xrange(j):
drange.append(i);
drange.append(i);
It should produce: [0, 0, 1, 1, 2, 2, ... j-1, j-1]
>>> j = 3
>>> drange = []
>>> for i in xrange(j):
... drange.extend([i]*2)
...
>>> drange
[0, 0, 1, 1, 2, 2]
or as a list comprehension
>>> drange = [i for i in xrange(j) for k in range(2)]
>>> drange
[0, 0, 1, 1, 2, 2]
In some cases this method can also be appropriate
>>> drange = [i//2 for i in xrange(j*2)]
>>> drange
[0, 0, 1, 1, 2, 2]
An answer using numpy
>>> import numpy as np
>>> j = 3
>>> np.repeat(np.array(xrange(j)), 2)
array([0, 0, 1, 1, 2, 2])
Use list comprehension then flatten the list:
>>> sum([ [i]*2 for i in xrange(5)],[])
[0, 0, 1, 1, 2, 2, 3, 3, 4, 4]
Here is a two-line alternative.
base= [2*[i] for i in range(5)]
drange = [item for x in base for item in x]