Repeat different elements of an array different amounts of times - python

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.

Related

Add a sequence of n numbers, getting n from another list, in Python

I have the following two lists:
numlist = [1, 1, 1, 1, 4, 1, 1, 4, 1, 2]
lenwords = [2,3,5]
I want to see the number at each index in len words as such:
for number in range(len(lenwords)):
print(lenwords[number])
And then take that number of items in numlist suggested by each index in lenwords (2,3,5) and add them together, like so:
add 1+1 then 1+1+4 then 1+1+4+1+2
I'm thinking that I could use itertools, but not sure how to do so.
I make an iterable out of numlist, then iterate over lenwords, using itertools.islice to pull out the count you want from the numlist generator.
https://docs.python.org/3/library/itertools.html#itertools.islice
import itertools
def sumlengths(numlist, lenwords):
numbers = iter(numlist)
for length in lenwords:
yield sum(itertools.islice(numbers, length))
numlist = [1, 1, 1, 1, 4, 1, 1, 4, 1, 2]
lenwords = [2,3,5]
print (*sumlengths(numlist, lenwords))
2 6 9
I did not validate the length of the inputs.
Another approach:
numlist = [1, 1, 1, 1, 4, 1, 1, 4, 1, 2]
lenwords = [2,3,5]
gen = iter(numlist)
result = []
for n in lenwords:
total = 0
for _ in range(n):
total += next(gen)
result.append(total)
The resulting list total is [2, 6, 9], as desired.
with out using ittertools:
numlist = [1, 1, 1, 1, 4, 1, 1, 4, 1, 2]
lenwords = [2, 3, 5]
counter = 0
for number in lenwords:
q = numlist[counter:counter+number]
print(sum(q))
counter += number
output
2
6
9

Given 2 lists (list_1, list_2) containing numbers 0 to (n-1), how do I obtain the permutation p (an element of S(n)) such that p(list_1) = list_2?

I have been using the sympy permutations package. So far I have declared permutations as follows
from sympy.combinatorics.generators import symmetric, Permutation
p = Permutation([[2, 3], [5]])
print(p(([0, 1, 2, 3, 4, 5]))
out:[0, 1, 3, 2, 4, 5]
I would like to declare a permutation given 2 lists. For example, I would like the element
I would like the permutation to act on integers rather than positions in the list (so that (01) * [1, 2, 3, 0] = [0, 2, 3, 1], instead of (01) * [1, 2, 3, 0] = [2, 1, 3, 0])
How can I do this ?
See the discussion about composition in permutations.py:
>>> start = Permutation([1, 0, 2, 3])
>>> finish = Permutation([2, 3, 1, 0])
>>> p = finish*start
>>> p([1,0,2,3])
[2, 3, 1, 0]
>>> p
Permutation(0, 2)(1, 3)
Maybe a better way to do this, but this seems to work if you want to access by name instead of position:
from sympy.combinatorics import Permutation
from sympy.utilities.iterables import permutations
P = Permutation
start = [1,0,2,3]
end = [2,3,1,0]
do = P(end)*P(start)
def byname(l):
a = do([l.index(i) for i in range(len(l))])
return [a.index(i) for i in range(len(l))]
for i in permutations(range(4)):
i, byname(i)

Pushing items in a list in Python

Let's say there's a list of [0, 3, 14, 0] and i want to 'push' the items of that list to the right corner. So the list will become [0, 0, 3, 14]. So basically the items with value > 0 will ignore the 0s and replace its position. The number could be anything (except 0) so sorting won't do it. Couple of examples:
[0, 4, 0, 4] => [0, 0, 4, 4]
[1, 0, 2, 2] => [0, 1, 2, 2]
[13, 0, 0, 6] => [0, 0, 13, 6]
Is there an efficient solution to this? I have been racking my brain for hours and i've found nothing near a solution.
If you want an efficient solution that is not inplace, and faster than sorting, you can do this:
lst = [0,1,2,0]
helper = [0 for i in len(lst)]
counter = 0
for i in range(len(lst)-1,-1,-1):
if lst[i]:
helper[len(lst)-1-counter] = lst[i]
counter += 1
print(helper)
This is probably not the most efficient solution:
dst_lst = [n for n in lst if n <= 0] + [n for n in lst if n > 0]
This will traverse the original list twice and create two temporary and one final list.
Hope this example helps!
Here we are using Python pre-defined data type queue
>>> import queue
>>> t = queue.deque()
>>> for each in [0, 4, 0, 4]:
... if each <= 0: t.appendleft(each)
... else: t.append(each)
...
>>> t
deque([0, 0, 4, 4])

Array of index values for unique elements in list

I have the following list:
x = np.array([1, 1, 2, 2, 2])
with np.unique values of [1, 2]
How do I generate the following list:
[1, 2, 1, 2, 3]
i.e. a running index from 1 for each of the unique elements in the list x.
you can use pandas.cumcount() after grouping by the value itself, it does exactly that:
Number each item in each group from 0 to the length of that group - 1.
try this:
import numpy as np
import pandas as pd
x = np.array([1, 1, 2, 2, 2])
places = list(pd.Series(x).groupby(by=x).cumcount().values + 1)
print(places)
Output:
[1, 2, 1, 2, 3]
Just use return_counts=True of np.unique with listcomp and np.hstack. It is still faster pandas solution
c = np.unique(x, return_counts=True)[1]
np.hstack([np.arange(item)+1 for item in c])
Out[869]: array([1, 2, 1, 2, 3], dtype=int64)
I'm not sure, if this is any faster or slower solution, but if you need just a list result with no pandas, you could try this
arr = np.array([1, 1, 2, 2, 2])
from collections import Counter
ranges = [range(1,v+1) for k,v in Counter(arr).items()]
result = []
for l in ranges:
result.extend(list(l))
print(result)
[1, 2, 1, 2, 3]
(or make your own counter with dict instead of Counter())

Python list comprehension mirroring values

I tried to figure out the following problem through list comprehension but I couldn't make it work. I will show you how I solved the problem using a loop and a list comprehension.
So, I have a list that can have 0 to 6 elements in a range(6) and when I apply my function on it I want to change the values, as shown here:
l = [0, 1, 2, 3, 4, 5]
mirror = [5, 4, 3, 2, 1, 0]
I don't want to just rotate the array by 180 degrees but I actually want to replace the values. For example, my list looks like this now:
l = [2, 5]
Then l_inverted list should look like this:
l_inverted = [3, 0]
I came up with a regular way to solve it but ever since I started learning Python I've preferred list comprehensions.
l = [0, 3, 5]
mirror = [5, 4, 3, 2, 1, 0]
i = 0
for element in l:
l[i] = mirror[element]
i += 1
This actually inverts the l list. Here's my approach using a list comprehension:
l = [3, 5]
mirror = [5, 4, 3, 2, 1, 0]
for element in l:
print(element)
l = [mirror[element] if x==element else x for x in l]
This works fine.
Until:
l = [0, 3, 5]
mirror = [5, 4, 3, 2, 1, 0]
for element in l:
print(element)
l = [mirror[element] if x==element else x for x in l]
So it will replace 5 with 0, 2 with 3 and both 5s (the new one too) become 0. Obviously, I don't want it like that.
Should I stick to the working solution or is there a smooth way to solve it with list comprehensions? I'm trying to practice list comprehensions at all times but it's not fully in my brain yet. Thanks a lot.
If you want it as a list comprehension:
>> l = [0, 3, 5]
>> mirror = [5, 4, 3, 2, 1, 0]
>> l_inverted = [mirror[x] for x in l]
>> l_inverted
[5, 2, 0]
You are drowning in a spoonful of water and trying to take us with you.
You are using bad naming conventions that make your simple problem complicated to comprehend.
orig = [0, 1, 2, 3, 4, 5]
orig_rev = l[::-1]
selector = [0, 3, 5]
result = [orig_rev[i] for i in selector]
print(result ) # [5, 2, 0]
Based on your first two examples, it seems you are looking for the complement of each list value according to some base, similar to ones' complement. You could either hard-code the base as 5 or whatever, or you could assume it's the maximum number in the list and calculate it. Here's a solution for the latter:
Concept
<this complement> = <max value in list> - <this value>
Code
values = [0, 3, 2, 4, 5]
max_value = max(values)
complements = [max_value - value for value in values]
print complements
Result
[5, 2, 3, 1, 0]

Categories

Resources