I want to create a date list that- contains the list of dates of one week but each date should be there 4 times in that list. like this:
[1-jan-2018, 1-jan-2018, 1-jan-2018, 1-jan-2018, 2-jan-2018, 2-jan-2018, 2-jan-2018, 2-jan-2018, 3-jan-2018, 3-jan-2018, 3-jan-2018, 3-jan-2018, 4-jan-2018, 4-jan-2018, 4-jan-2018, 4-jan-2018, 5-jan-2018, 5-jan-2018, 5-jan-2018, 5-jan-2018, 6-jan-2018, 6-jan-2018, 6-jan-2018, 6-jan-2018,7-jan-2018, 7-jan-2018, 7-jan-2018, 7-jan-2018]
I don't exactly have the idea how to do it but here is my attempt:
import pandas as pd
timeSeries = list(pd.date_range(start='1/1/2020', end='7/1/2020'))
print(timeSeries)
This will just create the list of dates of one week but I want the answer in the above format. Can someone please help?
How to duplicate items in a list
A solution is create various list with each element of your primary list repeated N time. In this example, I will duplicated each element four times, so:
old_list = [1,2,3,4]
# [i,i,i,i] will clone each item four times.
new_list = list([i,i,i,i] for i in old_list)
# new_list = [[1, 1, 1, 1], [2, 2, 2, 2], [3, 3, 3, 3], [4, 4, 4, 4]]
But, now you will have a list of lists, so you need to transform that result into a list of elements, this operation is called flat. In order to do this in python, you can use the itertools.chain.
import itertools
old_list = [1,2,3,4]
# [i,i,i,i] will clone each item four times.
new_list = list([i,i,i,i] for i in old_list)
# new_list = [[1, 1, 1, 1], [2, 2, 2, 2], [3, 3, 3, 3], [4, 4, 4, 4]]
new_list_flatten = list(itertools.chain(*new_list))
# new_list_flatten = [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4]
You can avoid the usage of * operation by calling itertools.chain.from_iterable:
import itertools
old_list = [1,2,3,4]
# [i,i,i,i] will clone each item four times.
new_list = list([i,i,i,i] for i in old_list)
# new_list = [[1, 1, 1, 1], [2, 2, 2, 2], [3, 3, 3, 3], [4, 4, 4, 4]]
new_list_flatten = list(itertools.chain.from_iterable(new_list))
# new_list_flatten = [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4]
Therefore, this is a code that do what you want:
import itertools
import pandas as pd
time_series = list(pd.date_range(start='1/1/2020', end='7/1/2020'))
newseries = list( itertools.chain.from_iterable((i,i,i,i) for i in time_series) )
print(newseries)
Related
I have a list of customers, and I want to generate a list of random numbers between 1 to 4 for each customer. I used the code below:
import numpy as np
import random
import pandas as pd
customer = [1, 2, 3]
for k in customer:
priority = list(range(1,5)) # list of integers from 1 to 4
random.shuffle(priority)
print(priority) # <- List of unique random numbers
[4, 1, 3, 2]
[3, 1, 2, 4]
[4, 3, 1, 2]
but I want to have a dictionary like:
priority = {1:[4, 1, 3, 2], 2:[3, 1, 2, 4], 3:[4, 3, 1, 2]}
How would I go about doing this in python?
Slight modifications to your existing loop is all you need. You can use your existing k to assign a new dictionary key & value:
import numpy as np
import random
import pandas as pd
customer = [1, 2, 3]
priority_dict = {}
for k in customer:
priority = list(range(1,5)) # list of integers from 1 to 4
random.shuffle(priority)
print(priority) # <- List of unique random numbers
priority_dict[k] = priority
#[4, 1, 3, 2]
#[3, 1, 2, 4]
#[4, 3, 1, 2]
print(priority_dict)
#{1: [3, 1, 4, 2], 2: [2, 1, 4, 3], 3: [1, 3, 2, 4]}
This question already has answers here:
Split List By Value and Keep Separators
(8 answers)
Closed 1 year ago.
Is there an easy way to split the list l below into 3 list. I want to cut the list when the sequence starts over. So every list should start with 1.
l= [1, 2, 3, 4, 5, 1, 2, 3, 4, 1, 2, 3, 4]
l1 = [1, 2, 3,4, 5]
l2=[1,2,3,4]
l3=[1,2,3,4]
My original thought was to look at the lead value and implement a condition inside a for loop that would cut the list when x.lead < x. But how do I use lead and lag when using lists in python?
NumPy solution
import numpy as np
l = [1, 2, 3, 4, 5, 1, 2, 3, 4, 1, 2, 3, 4]
parts = [list(i) for i in np.split(l,np.flatnonzero(np.diff(l)-1)+1)]
print(parts)
output
[[1, 2, 3, 4, 5], [1, 2, 3, 4], [1, 2, 3, 4]]
Explanation: I first find differences between adjacent elements using numpy.diff, then subtract 1 to be able to use numpy.flatnonzero to find where difference is other than 1, add 1 (note that numpy.diff output length is input length minus 1) to get indices for use in numpy.split, eventually convert it to list, as otherwise you would end with numpy.arrays
What about this:
l = [1, 2, 3, 4, 5, 1, 2, 3, 4, 1, 2, 3, 4]
one_indices = [i for i, e in enumerate(l) if e == 1]
slices = []
for count, item in enumerate(one_indices):
if count == len(one_indices) - 1:
slices.append((item, None))
else:
slices.append((item, one_indices[count + 1]))
sequences = [l[x[0] : x[1]] for x in slices]
print(sequences)
Out:
[[1, 2, 3, 4, 5], [1, 2, 3, 4], [1, 2, 3, 4]]
Another way without numpy,
l= [1, 2, 3, 4, 5, 1, 2, 3, 4, 1, 2, 3, 4]
start = 0
newlist = []
for i,v in enumerate(l):
if i!=0 and v==1:
newlist.append(l[start:i])
start = i
newlist.append(l[start:i+1])
print(newlist)
Working Demo: https://rextester.com/RYCV85570
I want to weave two lists and output all the possible results.
For example,
input: two lists l1 = [1, 2], l2 = [3, 4]
output: [1, 2, 3, 4], [1, 3, 2, 4], [1, 3, 4, 2], [3, 1, 2, 4], [3, 1, 4, 2], [3, 4, 1, 2]
Note: I need to keep the order in each list (e.g. 1 is always before 2, and 3 is always before 4)
The way I am solving this is by removing the head from one list, recursing, and then doing the same thing with the other list. The code is below:
all_possibles = []
def weaveLists(first, second, added):
if len(first) == 0 or len(second) == 0:
res = added[:]
res += first[:]
res += second[:]
all_possibles.append(res)
return
cur1 = first[0]
added.append(cur1)
first = first[1:]
weaveLists(first, second, added)
added = added[:-1]
first = [cur1] + first
cur2 = second[0]
added.append(cur2)
second = second[1:]
weaveLists(first, second, added)
added = added[:-1]
second = [cur2] + second
weaveLists([1, 2], [3, 4], [])
print(all_possibles)
The result I got is:
[[1, 2, 3, 4], [1, 3, 2, 4], [1, 3, 4, 2], [1, 3, 1, 2, 4], [1, 3, 1, 4, 2], [1, 3, 1, 4, 1, 2]]
I couldn't figure out why for the last three lists, the heading 1 from the first list is not removed.
Can anyone help? Thanks!
The reason you get those unexpected results is that you mutate added at this place:
added.append(cur1)
...this will affect the caller's added list (unintentionally). While the "undo" operation is not mutating the list:
added = added[:-1]
This creates a new list, and therefore this "undo" action does not roll back the change in the list of the caller.
The easy fix is to replace the call to append with:
added = added + [cur1]
And the same should happen in the second block.
It is easier if you pass the new values for the recursive call on-the-fly, and replace those two code blocks with just:
weaveLists(first[1:], second, added + [first[0]])
weaveLists(first, second[1:], added + [second[0]])
Here is another way to do it: we generate the possible indices of the items of the first list inside the weaved list, and fill the list accordingly.
We can generate the indices with itertools.combinations: it's the combinations of the indices of the weaved list, taking len(first_list) of them each time.
from itertools import combinations
def weave(l1, l2):
total_length = len(l1) + len(l2)
# indices at which to put items from l1 in the weaved output
for indices in combinations(range(total_length), r=len(l1)):
out = []
it1 = iter(l1)
it2 = iter(l2)
for i in range(total_length):
if i in indices:
out.append(next(it1))
else:
out.append(next(it2))
yield out
Sample run:
l1 = [1, 2]
l2 = [3, 4]
for w in weave(l1, l2):
print(w)
[1, 2, 3, 4]
[1, 3, 2, 4]
[1, 3, 4, 2]
[3, 1, 2, 4]
[3, 1, 4, 2]
[3, 4, 1, 2]
Another sample run with a longer list:
l1 = [1, 2]
l2 = [3, 4, 5]
for w in weave(l1, l2):
print(w)
[1, 2, 3, 4, 5]
[1, 3, 2, 4, 5]
[1, 3, 4, 2, 5]
[1, 3, 4, 5, 2]
[3, 1, 2, 4, 5]
[3, 1, 4, 2, 5]
[3, 1, 4, 5, 2]
[3, 4, 1, 2, 5]
[3, 4, 1, 5, 2]
[3, 4, 5, 1, 2]
i have a list [1, 2, 3]
i want to find number of times the elements of this list appears in a list of list:
lol = [[1, 2, 4, 5], [2, 3, 1, 2], [1, 2, 3], [3, 2, 6, 7, 1], [1, 4, 2, 6, 3]]
occurrences = 4
What I’m doing currently is the following:
a = [1, 2, 3]
lol = [[1, 2, 4, 5], [2, 3, 1, 2], [1, 2, 3], [3, 2, 6, 7, 1], [1, 4, 2, 6, 3]]
def get_count(a, b):
a = set(a)
return sum([a.issubset(x) for x in b])
print(get_count(a, lol))
This method works but is quite slow when I have 100s of 1000s of list to compare with a list of list (lol remains static!)
can we also preserve the "order" of the elements? there can be other elements in between. in this case occurrences will be 2 for the above case
Why not try:
testlist = lol ##Create a test list that we will work with
for i in range len(testlist): ##Start a loop that will repeat length of testlist times
if a in testlist: ##If/When it finds the first occurrence of the list a
Occurrences =+ 1 ##It adds 1 to the amount off occurences
Pos = testlist.index(a)
testlist.del(Pos) ##It deletes the instance from the list.
This should work
I have a list such as this:
original = [1, 2, 3, 4]
and another one of which I will find the sublists:
queries = [1, 4, 1, 5, 2, 3, 2, 1]
I want all the sublists which include only one instance of the original list. So in this example, I would get:
sublists = [ [1, 2, 3, 4], [1, 2], [1] ]
and my original would be left with:
original = [5]
How would I achieve this? Thank you
One slightly indirect approach would be to utilise the collections.Counter library object:
from collections import Counter
from itertools import zip_longest, repeat
original = [1, 2, 3, 4]
query = [1, 4, 1, 5, 2, 3, 2, 1]
cnts = Counter(query)
# cnts: Counter({1: 3, 2: 2, 4: 1, 5: 1, 3: 1})
sublists = zip_longest(*map(repeat, original, map(cnts.pop, original)))
# this creates the approprate number of copies of 1, 2, 3, 4 and (via
# zip_longest) shuffles them into lists with max one occurrence each
# sublists are padded with None's -- [(1, 2, 3, 4), (1, 2, None, None), (1, None, None, None)]
sublists = list(map(list, map(filter, repeat(bool), sublists)))
# None's are removed -- [[1, 2, 3, 4], [1, 2], [1]]
leftovers = list(filter(cnts.__contains__, query))
# [5]