Give an Array Element Labels from another Array - python

I have two Arrays:
data got 300 arrays in it with 31 Values each,
char got 300 arrays in it with 1 value each.
what is the best way to merge these two in this form:
x[0] = [{char[0], data[0]; char[1], data[1]; char[n], data[n]; char[299], data[299]}]
I need it to use Pandas Profiler to find correlations from data to their appointed chars.
tyvm!

You can do this:
import pandas as pd
# Example data and char arrays
data = [[1, 2, 3] for i in range(300)]
char = [i for i in range(300)]
combined = list(zip(char, data))
grouped = {}
for c, d in combined:
if c not in grouped:
grouped[c] = []
grouped[c].append(d)
dict_list = []
for c in range(300):
dict_list.append({'char': c, 'data': grouped[c]})
# Assign the list of dictionaries to x[0]
x = [dict_list]
values = [[d['char']] + d['data'] for d in dict_list]
# Assign the values to x[0]
x = [values]
which gives:
[(0, [1, 2, 3]),
(1, [1, 2, 3]),
(2, [1, 2, 3]),
(3, [1, 2, 3]),
(4, [1, 2, 3]),
(5, [1, 2, 3]),
(6, [1, 2, 3]),
(7, [1, 2, 3]),
(8, [1, 2, 3]),
(9, [1, 2, 3]),
(10, [1, 2, 3]),
(11, [1, 2, 3]),
(12, [1, 2, 3]),
(13, [1, 2, 3]),
(14, [1, 2, 3]),
(15, [1, 2, 3]),
(16, [1, 2, 3]),
(17, [1, 2, 3]),
(18, [1, 2, 3]),
(19, [1, 2, 3]),
(20, [1, 2, 3]),
(21, [1, 2, 3]),
(22, [1, 2, 3]),
(23, [1, 2, 3]),
(24, [1, 2, 3]),
(25, [1, 2, 3]),
(26, [1, 2, 3]),
(27, [1, 2, 3]),
(28, [1, 2, 3]),
(29, [1, 2, 3]),
(30, [1, 2, 3]),
(31, [1, 2, 3]),
(32, [1, 2, 3]),
(33, [1, 2, 3]),
(34, [1, 2, 3]),
(35, [1, 2, 3]),
(36, [1, 2, 3]),
(37, [1, 2, 3]),
(38, [1, 2, 3]),
(39, [1, 2, 3]),
(40, [1, 2, 3])
....
(293, [1, 2, 3]),
(294, [1, 2, 3]),
(295, [1, 2, 3]),
(296, [1, 2, 3]),
(297, [1, 2, 3]),
(298, [1, 2, 3]),
(299, [1, 2, 3])]

Related

How do I find all possible ways I can fit an array to 4 slots with the possibility of the array having more/less than 4 numbers?

Let's say I have 4 buckets and an array of numbers like [1,2,3,4,5]
| || || || |
|__||__||__||__|
1 2 3 4
5 2 3 4
1 5 3 4
etc...
I can also have less than 4 numbers like [1, 2, 3]
| || || || |
|__||__||__||__|
1 2 3
1 3 2
1 2 3
etc...
How do I find all possible combinations of the numbers in buckets (like [1,2,3,4] if length is >= 4 or [1,2,None,None] if length is < 4)?
You can use a recursive generator function:
def combos(nums, buckets, c = []):
if len(c) == buckets:
yield c
else:
if len(c) + len(nums) < buckets:
yield from combos(nums, buckets, c+[None])
for i, a in enumerate(nums):
yield from combos(nums[:i]+nums[i+1:], buckets, c+[a])
print(list(combos([1, 2, 3, 4, 5], 4)))
print(list(combos([1, 2, 3], 4)))
Output:
[[1, 2, 3, 4], [1, 2, 3, 5], [1, 2, 4, 3], [1, 2, 4, 5], [1, 2, 5, 3], [1, 2, 5, 4], [1, 3, 2, 4], [1, 3, 2, 5], [1, 3, 4, 2], [1, 3, 4, 5], [1, 3, 5, 2], [1, 3, 5, 4], [1, 4, 2, 3], [1, 4, 2, 5], [1, 4, 3, 2], [1, 4, 3, 5], [1, 4, 5, 2], [1, 4, 5, 3], [1, 5, 2, 3], [1, 5, 2, 4], [1, 5, 3, 2], [1, 5, 3, 4], [1, 5, 4, 2], [1, 5, 4, 3], [2, 1, 3, 4], [2, 1, 3, 5], [2, 1, 4, 3], [2, 1, 4, 5], [2, 1, 5, 3], [2, 1, 5, 4], [2, 3, 1, 4], [2, 3, 1, 5], [2, 3, 4, 1], [2, 3, 4, 5], [2, 3, 5, 1], [2, 3, 5, 4], [2, 4, 1, 3], [2, 4, 1, 5], [2, 4, 3, 1], [2, 4, 3, 5], [2, 4, 5, 1], [2, 4, 5, 3], [2, 5, 1, 3], [2, 5, 1, 4], [2, 5, 3, 1], [2, 5, 3, 4], [2, 5, 4, 1], [2, 5, 4, 3], [3, 1, 2, 4], [3, 1, 2, 5], [3, 1, 4, 2], [3, 1, 4, 5], [3, 1, 5, 2], [3, 1, 5, 4], [3, 2, 1, 4], [3, 2, 1, 5], [3, 2, 4, 1], [3, 2, 4, 5], [3, 2, 5, 1], [3, 2, 5, 4], [3, 4, 1, 2], [3, 4, 1, 5], [3, 4, 2, 1], [3, 4, 2, 5], [3, 4, 5, 1], [3, 4, 5, 2], [3, 5, 1, 2], [3, 5, 1, 4], [3, 5, 2, 1], [3, 5, 2, 4], [3, 5, 4, 1], [3, 5, 4, 2], [4, 1, 2, 3], [4, 1, 2, 5], [4, 1, 3, 2], [4, 1, 3, 5], [4, 1, 5, 2], [4, 1, 5, 3], [4, 2, 1, 3], [4, 2, 1, 5], [4, 2, 3, 1], [4, 2, 3, 5], [4, 2, 5, 1], [4, 2, 5, 3], [4, 3, 1, 2], [4, 3, 1, 5], [4, 3, 2, 1], [4, 3, 2, 5], [4, 3, 5, 1], [4, 3, 5, 2], [4, 5, 1, 2], [4, 5, 1, 3], [4, 5, 2, 1], [4, 5, 2, 3], [4, 5, 3, 1], [4, 5, 3, 2], [5, 1, 2, 3], [5, 1, 2, 4], [5, 1, 3, 2], [5, 1, 3, 4], [5, 1, 4, 2], [5, 1, 4, 3], [5, 2, 1, 3], [5, 2, 1, 4], [5, 2, 3, 1], [5, 2, 3, 4], [5, 2, 4, 1], [5, 2, 4, 3], [5, 3, 1, 2], [5, 3, 1, 4], [5, 3, 2, 1], [5, 3, 2, 4], [5, 3, 4, 1], [5, 3, 4, 2], [5, 4, 1, 2], [5, 4, 1, 3], [5, 4, 2, 1], [5, 4, 2, 3], [5, 4, 3, 1], [5, 4, 3, 2]]
[[None, 1, 2, 3], [None, 1, 3, 2], [None, 2, 1, 3], [None, 2, 3, 1], [None, 3, 1, 2], [None, 3, 2, 1], [1, None, 2, 3], [1, None, 3, 2], [1, 2, None, 3], [1, 2, 3, None], [1, 3, None, 2], [1, 3, 2, None], [2, None, 1, 3], [2, None, 3, 1], [2, 1, None, 3], [2, 1, 3, None], [2, 3, None, 1], [2, 3, 1, None], [3, None, 1, 2], [3, None, 2, 1], [3, 1, None, 2], [3, 1, 2, None], [3, 2, None, 1], [3, 2, 1, None]]
At each recursive call, if a combination has not yet been formed, the code does two things:
Checks if the specified number of buckets is greater than the input number list. If so, then the output is padded with None.
The remaining number list is iterated over, and each iteration value is added to the running result, and the recursion proceeds.
Use the built-in function itertools.permutations.
import itertools
def func(arr: list, slot_count=4):
if (v := slot_count - len(arr)) > 0:
arr.extend([None for _ in range(v)])
return itertools.permutations(arr, slot_count)
print(list(func([1, 2, 3])))
print(list(func([1, 2, 3, 4, 5])))
[(1, 2, 3, None), (1, 2, None, 3), (1, 3, 2, None), (1, 3, None, 2), (1, None, 2, 3), (1, None, 3, 2), (2, 1, 3, None), (2, 1, None, 3), (2, 3, 1, None), (2, 3, None, 1), (2, None, 1, 3), (2, None, 3, 1), (3, 1, 2, None), (3, 1, None, 2), (3, 2, 1, None), (3, 2, None, 1), (3, None, 1, 2), (3, None, 2, 1), (None, 1, 2, 3), (None, 1, 3, 2), (None, 2, 1, 3), (None, 2, 3, 1), (None, 3, 1, 2), (None, 3, 2, 1)]
[(1, 2, 3, 4), (1, 2, 3, 5), (1, 2, 4, 3), (1, 2, 4, 5), (1, 2, 5, 3), (1, 2, 5, 4), (1, 3, 2, 4), (1, 3, 2, 5), (1, 3, 4, 2), (1, 3, 4, 5), (1, 3, 5, 2), (1, 3, 5, 4), (1, 4, 2, 3), (1, 4, 2, 5), (1, 4, 3, 2), (1, 4, 3, 5), (1, 4, 5, 2), (1, 4, 5, 3), (1, 5, 2, 3), (1, 5, 2, 4), (1, 5, 3, 2), (1, 5, 3, 4), (1, 5, 4, 2), (1, 5, 4, 3), (2, 1, 3, 4), (2, 1, 3, 5), (2, 1, 4, 3), (2, 1, 4, 5), (2, 1, 5, 3), (2, 1, 5, 4), (2, 3, 1, 4), (2, 3, 1, 5), (2, 3, 4, 1), (2, 3, 4, 5), (2, 3, 5, 1), (2, 3, 5, 4), (2, 4, 1, 3), (2, 4, 1, 5), (2, 4, 3, 1), (2, 4, 3, 5), (2, 4, 5, 1), (2, 4, 5, 3), (2, 5, 1, 3), (2, 5, 1, 4), (2, 5, 3, 1), (2, 5, 3, 4), (2, 5, 4, 1), (2, 5, 4, 3), (3, 1, 2, 4), (3, 1, 2, 5), (3, 1, 4, 2), (3, 1, 4, 5), (3, 1, 5, 2), (3, 1, 5, 4), (3, 2, 1, 4), (3, 2, 1, 5), (3, 2, 4, 1), (3, 2, 4, 5), (3, 2, 5, 1), (3, 2, 5, 4), (3, 4, 1, 2), (3, 4, 1, 5), (3, 4, 2, 1), (3, 4, 2, 5), (3, 4, 5, 1), (3, 4, 5, 2), (3, 5, 1, 2), (3, 5, 1, 4), (3, 5, 2, 1), (3, 5, 2, 4), (3, 5, 4, 1), (3, 5, 4, 2), (4, 1, 2, 3), (4, 1, 2, 5), (4, 1, 3, 2), (4, 1, 3, 5), (4, 1, 5, 2), (4, 1, 5, 3), (4, 2, 1, 3), (4, 2, 1, 5), (4, 2, 3, 1), (4, 2, 3, 5), (4, 2, 5, 1), (4, 2, 5, 3), (4, 3, 1, 2), (4, 3, 1, 5), (4, 3, 2, 1), (4, 3, 2, 5), (4, 3, 5, 1), (4, 3, 5, 2), (4, 5, 1, 2), (4, 5, 1, 3), (4, 5, 2, 1), (4, 5, 2, 3), (4, 5, 3, 1), (4, 5, 3, 2), (5, 1, 2, 3), (5, 1, 2, 4), (5, 1, 3, 2), (5, 1, 3, 4), (5, 1, 4, 2), (5, 1, 4, 3), (5, 2, 1, 3), (5, 2, 1, 4), (5, 2, 3, 1), (5, 2, 3, 4), (5, 2, 4, 1), (5, 2, 4, 3), (5, 3, 1, 2), (5, 3, 1, 4), (5, 3, 2, 1), (5, 3, 2, 4), (5, 3, 4, 1), (5, 3, 4, 2), (5, 4, 1, 2), (5, 4, 1, 3), (5, 4, 2, 1), (5, 4, 2, 3), (5, 4, 3, 1), (5, 4, 3, 2)]

Iterating sublists without using the list length

I have a list of things, and I need to apply some processing on successive (and overlapping) groups of 3 elements:
I can do it with:
for i in range(len(things)-2):
process(things[i:i+3])
So for instance:
things=[0, 1, 2, 3, 4, 5, 6, 7]
And I want to process:
[0, 1, 2], [1, 2, 3], [2, 3, 4], [3, 4, 5], [4, 5, 6], [5, 6, 7]
But is there a clever (but readable) way to do it without explicitly using len(things)?
Yes, what you're looking for is called a sliding/moving window. There are different ways to achieve this but the easiest is to use tee() and islice() functions from itertools. Using this you can define a window() function like below with default window size of 2.
import itertools
def window(iterable, n=2):
iters = itertools.tee(iterable, n)
for i, it in enumerate(iters):
next(itertools.islice(it, i, i), None)
return zip(*iters)
Then you can use it as
>>> things=[0, 1, 2, 3, 4, 5, 6, 7]
>>> list(window(things, n = 3))
[(0, 1, 2), (1, 2, 3), (2, 3, 4), (3, 4, 5), (4, 5, 6), (5, 6, 7)]
>>> for elem in window(things, n = 3):
... print(elem)
...
(0, 1, 2)
(1, 2, 3)
(2, 3, 4)
(3, 4, 5)
(4, 5, 6)
(5, 6, 7)
Edit: For one time use a more simpler option may be
>>> list(zip(things, things[1:], things[2:]))
[(0, 1, 2), (1, 2, 3), (2, 3, 4), (3, 4, 5), (4, 5, 6), (5, 6, 7)]
Another way of doing it could be:
for i in things[0:-2]:
a=things.index(i)
process(things[a:a+3])
Let's try using enumerate, Here len(things[i : i+len_]) == len_ is to drop uneven sized list that get's accumulated at the end iterations.
len_ = 3
[things[i : i+len_] for i, j in enumerate(things) if len(things[i : i+len_]) == len_]
[[0, 1, 2], [1, 2, 3], [2, 3, 4], [3, 4, 5], [4, 5, 6], [5, 6, 7]]
len_ = 4
[things[i : i+len_] for i, j in enumerate(things) if len(things[i : i+len_]) == len_]
[[0, 1, 2, 3], [1, 2, 3, 4], [2, 3, 4, 5], [3, 4, 5, 6], [4, 5, 6, 7]]

How to insert elements from one list to another generating all possible combinations

Hello guys I need some help with lists in python. Suppose I have two lists.
a = [3,1,5]
b = [2,4]
What I want is to insert the elements of the list b consecutively (without changing the order of a) generating new lists. For example.
ans = [[2,4,3,1,5],[2,3,4,1,5],[2,3,1,4,5],[2,3,1,5,4],[3,2,4,1,5]...]
Thaks for your help I hope I was able to express myself correctly.
Not the most clean way of doing this, but here's what I mean:
from itertools import permutations
a = [3,1,5]
b = [2,4]
def a_order_is_same(perm):
i3, i1, i5 = perm.index(3), perm.index(1), perm.index(5)
return i3 < i1 < i5
ans = [p for p in permutations(a+b) if a_order_is_same(p)]
for p in ans:
print(p)
--------------------------------------------------
(3, 1, 5, 2, 4)
(3, 1, 5, 4, 2)
(3, 1, 2, 5, 4)
(3, 1, 2, 4, 5)
(3, 1, 4, 5, 2)
(3, 1, 4, 2, 5)
(3, 2, 1, 5, 4)
(3, 2, 1, 4, 5)
(3, 2, 4, 1, 5)
(3, 4, 1, 5, 2)
(3, 4, 1, 2, 5)
(3, 4, 2, 1, 5)
(2, 3, 1, 5, 4)
(2, 3, 1, 4, 5)
(2, 3, 4, 1, 5)
(2, 4, 3, 1, 5)
(4, 3, 1, 5, 2)
(4, 3, 1, 2, 5)
(4, 3, 2, 1, 5)
(4, 2, 3, 1, 5)
I give you another option.
import itertools
a = [3,1,5]
b = [2,4]
c = [b +[a]][0] #0 to get only one level of nested
perm = [x for x in itertools.permutations(c, 3)]
ans = []
Here is the formula to get your "ans" output:
for i in range(len(perm)):
groups = perm[i] #this is the subset like [2, 4, [3, 1, 5]]
#flatten the list or returns integer
clean = [y for x in groups for y in (x if isinstance(x,list) else [x])]
ans.append(clean)
print(clean)
[[2, 4, 3, 1, 5], [2, 3, 1, 5, 4], [4, 2, 3, 1, 5], [4, 3, 1, 5, 2], [3, 1, 5, 2, 4], [3, 1, 5, 4, 2]]

How to print an array in the form of key-value pairs in python?

I have a collection of arrays such as
a = [array([0, 1, 2, 3, 4]) array([0, 1, 2, 3]) array([0, 1, 2, 3, 4])
array([0, 1, 2, 3, 4, 5, 6, 7, 8]) array([0, 2, 3, 4, 5, 8, 9])
Is there any way to show this result is the form of key-value pairs like
[[(0),(1,2,3,4)],[(1),(0,2,3)],[(2),(0,1,3,4)],[(3),(0,1,2,4,5,6,7,8)]
[(4),(0,2,3,5,8,9)]]
i will get increment by 1 in the key and that value will be not included in the values list
I tried like this, but not able to put it into the required form.
c = [id for id in b if id != i] for i, b in enumerate(a)]
List comprehension with enumerate is one way. Note the comma after each single-item key. This represents that the object type is a tuple of length 1.
from numpy import array
a = [array([0, 1, 2, 3, 4]), array([0, 1, 2, 3]), array([0, 1, 2, 3, 4]),
array([0, 1, 2, 3, 4, 5, 6, 7, 8]), array([0, 2, 3, 4, 5, 8, 9])]
res = [[(i,), tuple(j for j in arr if j != i)] for i, arr in enumerate(a)]
# [[(0,), (1, 2, 3, 4)],
# [(1,), (0, 2, 3)],
# [(2,), (0, 1, 3, 4)],
# [(3,), (0, 1, 2, 4, 5, 6, 7, 8)],
# [(4,), (0, 2, 3, 4, 8, 9)]]
Alternatively, you can create a dictionary:
res_dict = {i: tuple(j for j in arr if j != i) for i, arr in enumerate(a)}
# {0: (1, 2, 3, 4),
# 1: (0, 2, 3),
# 2: (0, 1, 3, 4),
# 3: (0, 1, 2, 4, 5, 6, 7, 8),
# 4: (0, 2, 3, 4, 8, 9)}
You can try numpy approach:
import numpy as np
a = [np.array([0, 1, 2, 3, 4]),np.array([0, 1, 2, 3]),np.array([0, 1, 2, 3, 4]),
np.array([0, 1, 2, 3, 4, 5, 6, 7, 8]), np.array([0, 2, 3, 4, 5, 8, 9])]
print([[(i,),tuple(np.delete(j,np.argwhere(j==i)))] for i,j in enumerate(a)])
output:
[[(0,), (1, 2, 3, 4)], [(1,), (0, 2, 3)], [(2,), (0, 1, 3, 4)], [(3,), (0, 1, 2, 4, 5, 6, 7, 8)], [(4,), (0, 2, 3, 5, 8, 9)]]

Grouping the combination results into a list with sub-lists

I have list a:
a = [0,1,2,3,4,5]
Then I create all three-element combinations of this list. The results are grouped in sublistach because of matching to the equivalent in the form of a binary 3-bit string. For example, the result [0,4,5] corresponds to the sequence 001, because each even number corresponds to 0, and the odd number 1.
The code I use with the comments:
import itertools as it
import itertools
# I create three-element combinations of zeros and ones
combinations_3bit = list(map(list, itertools.product([0,1], repeat=3)))
# output: [[0, 0, 0], [0, 0, 1], [0, 1, 0], [0, 1, 1], [1, 0, 0], [1, 0, 1], [1, 1, 0], [1, 1, 1]]
# I create a list of strings with values from the list `3bit_combinations`
a=[]
for i in range(len(combinations_3bit)):
a2 =''.join(map(str, [1 if x%2 else 0 for x in combinations_3bit[i]]))
a.append(a2)
# output: ['000', '001', '010', '011', '100', '101', '110', '111']
# I remove repetitions in pairs of type 001 with 100, 011 with 110, etc.
combinations_3bit_without_repetition = [v for k, v in enumerate(a) if v[::-1] not in a[:k]]
# output: ['000', '001', '010', '011', '101', '111']
b = [0,1,2,3,4,5]
good = []
for i in range(len(combinations_3bit_without_repetition)):
c=[]
for u in it.combinations(b, 3):
u1 = list(u)
y =''.join(map(str, [1 if x%2 else 0 for x in u1]))
if y == combinations_3bit_without_repetition[i]:
c.append(u1)
good.append(c)
# output: [[[0, 2, 4]], [[0, 2, 3], [0, 2, 5], [0, 4, 5], [2, 4, 5]], [[0, 1, 2], [0, 1, 4], [0, 3, 4], [2, 3, 4]], [[0, 1, 3], [0, 1, 5], [0, 3, 5], [2, 3, 5]], [[1, 2, 3], [1, 2, 5], [1, 4, 5], [3, 4, 5]], [[1, 3, 5]]]
Can this be solved nicer and more economically?
Because the above solution seems to be "around" and for example the function it.combinations returns after each indexi from the list combinations_3bit_without_repetition all possible combinations, and only then the condition screens only the matching ones. In the case of large lists, this solution is weak;)
There is a much better way to generate the binary strings that you need:
import itertools
strings = ['{0:03b}'.format(i) for i in range(8)]
b = [0,1,2,3,4,5]
combinations = [list(x) for x in itertools.combinations(b, 3)]
dct = {}
for x in combinations:
y = ''.join(str(j%2) for j in x)
if y in dct:
dct[y].append(x)
else:
dct[y] = [x]
print(dct)
Output:
{'010': [[0, 1, 2], [0, 1, 4], [0, 3, 4], [2, 3, 4]], '011': [[0, 1, 3], [0, 1, 5], [0, 3, 5], [2, 3, 5]], '001': [[0, 2, 3], [0, 2, 5], [0, 4, 5], [2, 4, 5]], '000': [[0, 2, 4]], '101': [[1, 2, 3], [1, 2, 5], [1, 4, 5], [3, 4, 5]], '100': [[1, 2, 4]], '110': [[1, 3, 4]], '111': [[1, 3, 5]]}
Check to see if this does what you need. It creates a dictionary, where each key is a length 3 binary string, and each value is an array of combinations that match the binary string.
Here is an itertools.groupby solution using your b and your combinations_3bit_without_repetition:
def binarize(x):
return ''.join(map(str, map((1).__and__, x)))
srted = sorted(itertools.combinations(b, 3), key=binarize)
allowed = set(combinations_3bit_without_repetition)
result = [list(grp) for bn, grp in itertools.groupby(srted, binarize) if bn in allowed]
print(result)
Prints:
[[(0, 2, 4)], [(0, 2, 3), (0, 2, 5), (0, 4, 5), (2, 4, 5)], [(0, 1, 2), (0, 1, 4), (0, 3, 4), (2, 3, 4)], [(0, 1, 3), (0, 1, 5), (0, 3, 5), (2, 3, 5)], [(1, 2, 3), (1, 2, 5), (1, 4, 5), (3, 4, 5)], [(1, 3, 5)]]

Categories

Resources