Adding a n extra colum from another matrix - python

I have these two matrices:
A = [[2, 7, 3, 6], [3, 3, 4, 4], [6, 9, 5, 3], [4, 2, 1, 7]]
B = [[2, 6, 3, 5], [-1, 2, -3, 1], [2, -5, 7, 3]]
I need to create three matrices A+1st column of B, and so on
So I need this final result:
A1 = [[2, 7, 3, 6, 2], [3, 3, 4, 4, 6], [6, 9, 5, 3, 3], [4, 2, 1, 7, 5]]
A2 = [[2, 7, 3, 6, -1], [3, 3, 4, 4, 2], [6, 9, 5, 3, -3], [4, 2, 1, 7, 7]]
A3 = [[2, 7, 3, 6, 2], [3, 3, 4, 4, -5], [6, 9, 5, 3, 7], [4, 2, 1, 7, 3]]
I start doing the following code, but I only got one of those
for j in range(len(B)):
for i in range(j):
b = B[j][i]
A = [x + [b] for x in A]
print(A)
Output:
[[2, 7, 3, 6], [3, 3, 4, 4], [6, 9, 5, 3], [4, 2, 1, 7]]
[[2, 7, 3, 6, -1], [3, 3, 4, 4, -1], [6, 9, 5, 3, -1], [4, 2, 1, 7, -1]]
[[2, 7, 3, 6, -1, 2, -5], [3, 3, 4, 4, -1, 2, -5], [6, 9, 5, 3, -1, 2, -5], [4, 2, 1, 7, -1, 2, -5]]
Process finished with exit code 0

You can leverage enumerate() to get your output:
A = [[2, 7, 3, 6], [3, 3, 4, 4], [6, 9, 5, 3], [4, 2, 1, 7]]
B = [[2, 6, 3, 5], [-1, 2, -3, 1], [2, -5, 7, 3]]
AA ={}
for idx,inner in enumerate(B):
# add to each a from A the k-th elem of your inner
AA[f"A{idx}"] = [a +[inner[k]] for k,a in enumerate(A)]
print(AA) # stored the lists into a dict
{'A0': [[2, 7, 3, 6, 2], [3, 3, 4, 4, 6], [6, 9, 5, 3, 3], [4, 2, 1, 7, 5]],
'A1': [[2, 7, 3, 6, -1], [3, 3, 4, 4, 2], [6, 9, 5, 3, -3], [4, 2, 1, 7, 1]],
'A2': [[2, 7, 3, 6, 2], [3, 3, 4, 4, -5], [6, 9, 5, 3, 7], [4, 2, 1, 7, 3]]}
As a personal preference I avoid using range(len(...)) where I can - enumerate is cleaner.
If string literals do not work for you, use "A{}".format(idx) instead.
Your code does not work because you coupled the range of i to j
for j in range(len(B)): # j starts as 0,1,2
for i in range(j): # i is doing nothing, 0, 0+1 <-- wrong

This is a possible solution that you can certainly start with:
k = len(A)
D = []
for i in range(len(B)):
D.append([])
for j in range(len(A)):
C = A[j][:k]
C.append(B[i][j])
D[i].append(C)

Make sure to use deepcopy so that they are not all referring to the same object.
A = [[2, 7, 3, 6], [3, 3, 4, 4], [6, 9, 5, 3], [4, 2, 1, 7]]
B = [[2, 6, 3, 5], [-1, 2, -3, 1], [2, -5, 7, 3]]
from copy import deepcopy
A_list = [deepcopy(A) for i in range(3)]
for outer_idx, list_in_b in enumerate(B):
for inner_idx, value in enumerate(list_in_b):
A_list[outer_idx][inner_idx].append(value)
print(A_list)
# Output:
#[[[2, 7, 3, 6, 2], [3, 3, 4, 4, 6], [6, 9, 5, 3, 3], [4, 2, 1, 7, 5]],
# [[2, 7, 3, 6, -1], [3, 3, 4, 4, 2], [6, 9, 5, 3, -3], [4, 2, 1, 7, 1]],
# [[2, 7, 3, 6, 2], [3, 3, 4, 4, -5], [6, 9, 5, 3, 7], [4, 2, 1, 7, 3]]]

Related

Is there an alternate way to do the same without for loop?

I have two numpy arrays A and l. The dimension of A is (n, x, y) and the dimension of l is (n,1). I get the result as follows:
res = []
for i in range(n):
res.append(A[i, x, l[i])
This way of getting the result is very time consuming for a larger value of n. Is there an alternative to get the same result quickly?
If 0<=l[i]<y for all values of i:
>>> n,x,y = 4,5,6
>>> A = np.random.randint(0,10,(n,x,y))
array([[[3, 3, 3, 8, 7, 0],
[8, 1, 1, 5, 3, 8],
[0, 1, 0, 4, 1, 3],
[2, 2, 1, 8, 6, 5],
[2, 5, 9, 2, 6, 3]],
[[9, 7, 4, 6, 7, 7],
[1, 7, 0, 4, 9, 6],
[8, 0, 8, 6, 7, 8],
[1, 9, 7, 8, 7, 6],
[2, 4, 6, 3, 6, 8]],
[[2, 8, 5, 7, 9, 4],
[7, 2, 2, 5, 2, 1],
[0, 8, 6, 4, 1, 2],
[6, 9, 9, 0, 2, 4],
[9, 9, 1, 6, 7, 0]],
[[3, 8, 4, 3, 5, 6],
[5, 3, 7, 7, 4, 6],
[9, 0, 7, 9, 2, 1],
[1, 6, 2, 2, 9, 5],
[5, 0, 9, 0, 5, 2]]])
>>> l = np.random.randint(low=0, high=y-1, size=(n,1))
array([[0],
[1],
[3],
[1]])
>>> x0 = 2
>>> res = []
>>> for i in range(n):
res.append(A[i, x0, l[i])
>>> res
[array([0]), array([0]), array([4]), array([0])]
numpy:
>>> A[range(n), 2, l.flatten()]
array([0, 0, 4, 0])
what about list comprehension?
res=[A[i, x, l[i] for i in range(n)]

How to get data out of an array

I have an array as such from a txt file:
[[1, 4, 6, 2, 5]
[3, 4, 3, 5, 4]
[5, 3, 6, 7, 1]]
[[3, 4, 2, 5, 8]
[5, 2, 7, 5, 4]
[4, 2, 4, 4, 0]]
[[2, 5, 3, 1, 4]
[3, 8, 5, 6, 2]
[2, 6, 7, 4, 2]]
I want to take the mean of the 3rd row for each group of results. so each group is in a double bracket [[1, 4, 6, 2, 5]
[3, 4, 3, 5, 4]
[5, 3, 6, 7, 1]] is one group,
[[3, 4, 2, 5, 8]
[5, 2, 7, 5, 4]
[4, 2, 4, 4, 0]] is the second group etc.)
How do I access each group individually?
If you want to take the mean of the third row of each group with:
>>> data[:,2].mean(axis=1)
array([4.4, 2.8, 4.2])
If data is for example:
>>> data
array([[[1, 4, 6, 2, 5],
[3, 4, 3, 5, 4],
[5, 3, 6, 7, 1]],
[[3, 4, 2, 5, 8],
[5, 2, 7, 5, 4],
[4, 2, 4, 4, 0]],
[[2, 5, 3, 1, 4],
[3, 8, 5, 6, 2],
[2, 6, 7, 4, 2]]])
then by slicing, we obtain the third row of each group:
>>> data[:,2]
array([[5, 3, 6, 7, 1],
[4, 2, 4, 4, 0],
[2, 6, 7, 4, 2]])
Then for each row we can calculate the mean with .mean(axis=1)
If your data is like this, This code will work fine
lst =[
[[1, 4, 6, 2, 5],[3, 4, 3, 5, 4],[5, 3, 6, 7, 1]],
[[3, 4, 2, 5, 8],[5, 2, 7, 5, 4],[4, 2, 4, 4, 0]],
[[2, 5, 3, 1, 4],[3, 8, 5, 6, 2],[2, 6, 7, 4, 2]]
]
import numpy as np
means = []
for i in lst:
means.append(np.mean(i[2]))
print(means)
>> [4.4, 2.8, 4.2]

How to count the number of sublists based on common elements from a nested list in python?

I have a list of lists like this: [[1, 2, 3, 4, 5, 6, 7, 8, 9], [1, 2, 3, 4, 5], [2, 3, 4, 5, 6, 7], [2, 3], [3, 4]]. How can I count the lists which are sublists of more than two lists? For example, here [2, 3] and [3, 4] would be the lists that are sublists of first 3 lists. I want to get rid of them.
This comprehension should do it:
data = [[1, 2, 3, 4, 5, 6, 7, 8, 9], [1, 2, 3, 4, 5], [2, 3, 4, 5, 6, 7], [2, 3], [3, 4]]
solution = [i for i in data if sum([1 for j in data if set(i).issubset(set(j))]) < 3]
set_list = [[1, 2, 3, 4, 5, 6, 7, 8, 9], [1, 2, 3, 4, 5], [2, 3, 4, 5, 6, 7], [2, 3], [3, 4]]
check_list = [[2, 3], [3, 4]]
sublist_to_list = {}
for set in set_list:
for i, sublist in enumerate(check_list):
count = 0
for element in sublist:
if element in set:
count += 1
if count == len(sublist):
if i not in sublist_to_list:
sublist_to_list[i] = [set]
else:
sublist_to_list[i].append(set)
print(sublist_to_list)
Output: {0: [[1, 2, 3, 4, 5, 6, 7, 8, 9], [1, 2, 3, 4, 5], [2, 3, 4, 5, 6, 7], [2, 3]], 1: [[1, 2, 3, 4, 5, 6, 7, 8, 9], [1, 2, 3, 4, 5], [2, 3, 4, 5, 6, 7], [3, 4]]}
which means [2, 3] is subset of [[1, 2, 3, 4, 5, 6, 7, 8, 9], [1, 2, 3, 4, 5], [2, 3, 4, 5, 6, 7], [2, 3]]
and [3, 4] is subset of [[1, 2, 3, 4, 5, 6, 7, 8, 9], [1, 2, 3, 4, 5], [2, 3, 4, 5, 6, 7], [3, 4]]
You can first make a function that gets sub lists of a list:
def sublists(lst):
length = len(lst)
for size in range(1, length + 1):
for start in range(length - size + 1):
yield lst[start:start+size]
Which works as follows:
>>> list(sublists([1, 2, 3, 4, 5]))
[[1], [2], [3], [4], [5], [1, 2], [2, 3], [3, 4], [4, 5], [1, 2, 3], [2, 3, 4], [3, 4, 5], [1, 2, 3, 4], [2, 3, 4, 5], [1, 2, 3, 4, 5]]
Then you can use this to collect all the sublists list indices into a collections.defaultdict:
from collections import defaultdict
lsts = [[1, 2, 3, 4, 5, 6, 7, 8, 9], [1, 2, 3, 4, 5], [2, 3, 4, 5, 6, 7], [2, 3], [3, 4]]
d = defaultdict(list)
for i, lst in enumerate(lsts):
subs = sublists(lst)
while True:
try:
curr = tuple(next(subs))
d[curr].append(i)
except StopIteration:
break
Which will have tuple keys for the sublists, and the list indices as the values.
Then to determine sub lists that occur more than twice in all the lists, you can check if the set of all the indices has a length of more than two:
print([list(k) for k, v in d.items() if len(set(v)) > 2])
Which will give the following sublists:
[[2], [3], [4], [5], [2, 3], [3, 4], [4, 5], [2, 3, 4], [3, 4, 5], [2, 3, 4, 5]]

[Python]: generate and array of all possible combinations

I have a very straightforward combination problem. I have two arrays (a and b). Array a indicates all the values one of the three slots in array b can take on. Each slot in array b can have a value between 1 and 5. An example of which would be [1, 4, 5]. I would like to generate an array (c) with all possible combinations. I like to extend the basic example larger arrays.
Input:
a = [1, 2, 3, 4, 5]
b = [1, 2, 3]
Output:
c = [[1, 1, 1], [1, 1, 2],[1, 1, 3], [1, 1, 4], [1, 1, 5],
[1, 2, 1], [1, 2, 2],[1, 2, 3], [1, 2, 4], [1, 2, 5],
[1, 3, 1], [1, 3, 2],[1, 3, 3], [1, 3, 4], [1, 3, 5],
[1, 4, 1], [1, 4, 2],[1, 4, 3], [1, 4, 4], [1, 4, 5],
[1, 5, 1], [1, 5, 2],[1, 5, 3], [1, 5, 4], [1, 5, 5],
[2, 1, 1], [2, 1, 2],[2, 1, 3], [2, 1, 4], [2, 1, 5],
[2, 2, 1], [2, 2, 2],[2, 2, 3], [2, 2, 4], [2, 2, 5],
[2, 3, 1], [2, 3, 2],[2, 3, 3], [2, 3, 4], [2, 3, 5],
[2, 4, 1], [2, 4, 2],[2, 4, 3], [2, 4, 4], [2, 4, 5],
[2, 5, 1], [2, 5, 2],[2, 5, 3], [2, 5, 4], [2, 5, 5],
[3, 1, 1], [3, 1, 2],[3, 1, 3], [3, 1, 4], [3, 1, 5],
[3, 2, 1], [3, 2, 2],[3, 2, 3], [3, 2, 4], [3, 2, 5],
[3, 3, 1], [3, 3, 2],[3, 3, 3], [3, 3, 4], [3, 3, 5],
[3, 4, 1], [3, 4, 2],[3, 4, 3], [3, 4, 4], [3, 4, 5],
[3, 5, 1], [3, 5, 2],[3, 5, 3], [3, 5, 4], [3, 5, 5],
[4, 1, 1], [4, 1, 2],[4, 1, 3], [4, 1, 4], [4, 1, 5],
[4, 2, 1], [4, 2, 2],[4, 2, 3], [4, 2, 4], [4, 2, 5],
[4, 3, 1], [4, 3, 2],[4, 3, 3], [4, 3, 4], [4, 3, 5],
[4, 4, 1], [4, 4, 2],[4, 4, 3], [4, 4, 4], [4, 4, 5],
[5, 5, 1], [5, 5, 2],[5, 5, 3], [5, 5, 4], [5, 5, 5],
[5, 1, 1], [5, 1, 2],[5, 1, 3], [5, 1, 4], [5, 1, 5],
[5, 2, 1], [5, 2, 2],[5, 2, 3], [5, 2, 4], [5, 2, 5],
[5, 3, 1], [5, 3, 2],[5, 3, 3], [5, 3, 4], [5, 3, 5],
[5, 4, 1], [5, 4, 2],[5, 4, 3], [5, 4, 4], [5, 4, 5],
[5, 5, 1], [5, 5, 2],[5, 5, 3], [5, 5, 4], [5, 5, 5]]
Solution for the problem above:
d = []
for i in range(len(a)):
for j in range(len(a)):
for k in range(len(a)):
e = []
e.append(i+1)
e.append(j+1)
e.append(k+1)
d.append(e)
I am looking for a more generic way. One which can accommodate larger arrays (see below) without the need to use a nested for loop structure. I searched for a comparable example, but was unable to find one on stackoverflow.
Input:
a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
b = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
You are looking for itertools.product().
a = [1, 2, 3, 4, 5]
b = 3 # Actually, you just need the length of the array, values do not matter
c = itertools.product(a, repeat=b)
Note that this returns an iterator, you may need to cast it using list() but be aware this can take forever and highly consume memory if the sizes grow.
In the general case, you should of course use the itertools module, in this particular case itertools.product, as explained in the other answer.
If you want to implement the function yourself, you can use recursion to make it applicable to any array sizes. Also, you should probably make it a generator function (using yield instead of return), as the result could be rather long. You can try something like this:
def combinations(lst, num):
if num > 0:
for x in lst:
for comb in combinations(lst, num - 1):
yield [x] + comb
else:
yield []

Unpack items and add a new one

I need to create a new list merging two lists where one of them is a list of lists. Here's what I need to do:
a = [[2, 1, 4, 5, 0], [3, 6, 5, 4, 8], [2, 1, 4, 7, 8], [3, 4, 9, 5, 6], [7, 5, 2, 1, 1]]
b = [2, 3, 5, 0, 8]
c = []
for indx, item in enumerate(a):
c.append([item, b[indx]])
This generates c as:
[[[2, 1, 4, 5, 0], 2], [[3, 6, 5, 4, 8], 3], [[2, 1, 4, 7, 8], 5], [[3, 4, 9, 5, 6], 0], [[7, 5, 2, 1, 1], 8]]
but I would need it to look like:
[[2, 1, 4, 5, 0, 2], [3, 6, 5, 4, 8, 3], [2, 1, 4, 7, 8, 5], [3, 4, 9, 5, 6, 0], [7, 5, 2, 1, 1], 8]
I've tried adding a * in front of item to unpack the elements but that doesn't work.
Just concatenate the items to create a new list from item and the element from b:
for indx, item in enumerate(a):
c.append(item + [b[indx]])
You can simplify your loop using the zip() function:
for a_item, b_item in zip(a, b):
c.append(a_item + [b_item])
Then move the whole definition of c to a list comprehension:
c = [a_item + [b_item] for a_item, b_item in zip(a, b)]
Demo:
>>> a = [[2, 1, 4, 5, 0], [3, 6, 5, 4, 8], [2, 1, 4, 7, 8], [3, 4, 9, 5, 6], [7, 5, 2, 1, 1]]
>>> b = [2, 3, 5, 0, 8]
>>> [a_item + [b_item] for a_item, b_item in zip(a, b)]
[[2, 1, 4, 5, 0, 2], [3, 6, 5, 4, 8, 3], [2, 1, 4, 7, 8, 5], [3, 4, 9, 5, 6, 0], [7, 5, 2, 1, 1, 8]]
You can make use of zip() function and list comprehension:
>>> a = [[2, 1, 4, 5, 0], [3, 6, 5, 4, 8], [2, 1, 4, 7, 8], [3, 4, 9, 5, 6], [7, 5, 2, 1, 1]]
>>> b = [2, 3, 5, 0, 8]
>>> [elem1 + [elem2] for elem1, elem2 in zip(a, b)]
[[2, 1, 4, 5, 0, 2], [3, 6, 5, 4, 8, 3], [2, 1, 4, 7, 8, 5], [3, 4, 9, 5, 6, 0], [7, 5, 2, 1, 1, 8]]

Categories