Let's say a have a list of lists in Python:
list_of_values = [[a, b, c], [d, e, f], [g, h, i], [j, k, l]]
And I want to convert automatically to independent lists like:
list1 = [[a, b, c],[d + g + j, e + h + k, f + i + l]]
list2 = [[d, e, f], [g + j, h + k, i + l]]
list3 = [[g, h, i], [j, k, l]]
Let's say I have a list of lists of integers in Python:
list_of_values = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
And I want to convert automatically to independent lists like:
list1 = [[1, 2, 3],[4 + 7 + 10, 5 + 8 + 11, 6 + 9 + l2]]
list2 = [[4, 5, 6], [7 + 10, 8 + 11, 9 + 12]]
list3 = [[7, 8, 9], [10, 11, l2]]
Performing the math:
list1 = [[1, 2, 3], [21, 24, 27]]
list2 = [[4, 5, 6], [17, 19, 21]]
list3 = [[7, 8, 9], [10, 11, l2]]
For your updated Question:
Suppose you have "list of lists of strings" like below:
s = [['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i'], ['j', 'k', 'l']]
Then you can use: join to concatenate:
>>> for i in range(len(s)):
... [s[i], map(lambda t: ''.join(t), zip(*s[i + 1:]))]
...
[['a', 'b', 'c'], ['dgj', 'ehk', 'fil']]
[['d', 'e', 'f'], ['gj', 'hk', 'il']]
[['g', 'h', 'i'], ['j', 'k', 'l']]
[['j', 'k', 'l'], []]
If you don't need last line in output then just use range argument less then one of length:
>>> for i in range(len(s)-1):
... [s[i], map(''.join, zip(*s[i + 1:]))] # remove lambda function
...
[['a', 'b', 'c'], ['dgj', 'ehk', 'fil']]
[['d', 'e', 'f'], ['gj', 'hk', 'il']]
[['g', 'h', 'i'], ['j', 'k', 'l']]
But suppose if you have "list of lists of numbers" e.g.:
l = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
Then you can use sum function:
>>> for i in range(len(l) - 1):
... [l[i], map(sum, zip(*l[i + 1:]))]
...
[[1, 2, 3], [21, 24, 27]]
[[4, 5, 6], [17, 19, 21]]
[[7, 8, 9], [10, 11, 12]]
Edit:..
If you wants to make single function for both strings and number then you canmake use of add() operator from operator library.
Check add() function:
>>> from operator import add
>>> add(1, 2)
3
>>> add('1', '2') # this is like + works
'12'
Now, using it make a new my_add() that add all elements in a sequence, check following codes:
>>> def my_add(t):
... return reduce(add, t)
...
>>> my_add(('a', 'b'))
'ab'
>>> my_add((2, 1))
3
Now, write a function using my_add() function that will so your work:
def do_my_work(s):
for i in range(len(s)-1):
print [s[i], map(my_add, zip(*s[i + 1:]))]
Now, see how this works for you:
>>> s
[['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i'], ['j', 'k', 'l']]
>>> do_my_work(s)
[['a', 'b', 'c'], ['dgj', 'ehk', 'fil']]
[['d', 'e', 'f'], ['gj', 'hk', 'il']]
[['g', 'h', 'i'], ['j', 'k', 'l']]
>>> l
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
>>> do_my_work(l) # so same function for str and int both!
[[1, 2, 3], [21, 24, 27]]
[[4, 5, 6], [17, 19, 21]]
[[7, 8, 9], [10, 11, 12]]
>>> import itertools
>>> lst = [['a', 'b', 'c'], ['d', 'e', 'f'], ['g', 'h', 'i'], ['j', 'k', 'l']]
>>> for i, item in enumerate(lst):
print [item, itertools.chain.from_iterable(lst[i+1:])]
[['a', 'b', 'c'], ['d', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l']]
[['d', 'e', 'f'], ['g', 'h', 'i', 'j', 'k', 'l']]
[['g', 'h', 'i'], ['j', 'k', 'l']]
[['j', 'k', 'l'], []]
for i in range(len(list_of_values) - 1):
print [list_of_values[i]] + [map(list, zip(*list_of_values[i+1:]))]
Output
[['a', 'b', 'c'], [['d', 'g', 'j'], ['e', 'h', 'k'], ['f', 'i', 'l']]]
[['d', 'e', 'f'], [['g', 'j'], ['h', 'k'], ['i', 'l']]]
[['g', 'h', 'i'], [['j'], ['k'], ['l']]]
For the numbers, you can simply do
list_of_values = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]
for i in range(len(list_of_values) - 1):
print [list_of_values[i]] + [map(sum, zip(*list_of_values[i+1:]))]
Output
[[1, 2, 3], [21, 24, 27]]
[[4, 5, 6], [17, 19, 21]]
[[7, 8, 9], [10, 11, 12]]
Related
How can I copy each row of an array n times?
So if I have a 2x3 array, and I copy each row 3 times, I will have a 6x3 array. For example, I need to convert A to B below:
A = np.array([[1, 2, 3],
[4, 5, 6]])
B = np.array([[1, 2, 3],
[1, 2, 3],
[1, 2, 3],
[4, 5, 6],
[4, 5, 6],
[4, 5, 6]])
If possible, I would like to avoid a for loop.
If I read correctly, this is probably what you want assuming you started with mat:
transformed = np.concatenate([np.vstack([mat[:, i]] * 3).T for i in range(mat.shape[1])], axis=1)
Here's a verifiable example:
# mocking a starting array
import string
mat = np.random.choice(list(string.ascii_lowercase), size=(5,3))
>>> mat
array([['s', 'r', 'e'],
['g', 'v', 'c'],
['i', 'b', 'd'],
['f', 'g', 's'],
['o', 'm', 'w']], dtype='<U1')
Transform it:
# this repeats it 3 times for sake of displaying
transformed = np.concatenate([np.vstack([mat[i, :]] * 3).T for i in range(mat.shape[0])], axis=1).T
>>> transformed
array([['s', 'r', 'e'],
['s', 'r', 'e'],
['s', 'r', 'e'],
['g', 'v', 'c'],
['g', 'v', 'c'],
['g', 'v', 'c'],
['i', 'b', 'd'],
['i', 'b', 'd'],
['i', 'b', 'd'],
['f', 'g', 's'],
['f', 'g', 's'],
['f', 'g', 's'],
['o', 'm', 'w'],
['o', 'm', 'w'],
['o', 'm', 'w']], dtype='<U1')
The idea of this is to use vstack to concatenate each column to itself multiple time, and then concatenate the result of that to get the final array.
You can use np.repeat with integer positional indexing:
B = A[np.repeat(np.arange(A.shape[0]), 3)]
array([[1, 2, 3],
[1, 2, 3],
[1, 2, 3],
[4, 5, 6],
[4, 5, 6],
[4, 5, 6]])
v1=[3,2]
v3=v1[:]*10
print(v3)
np.repeat is exactly what you are looking for. You can use the axis option to specify that you want to duplicate rows.
B = np.repeat(A, 3, axis=0)
Is not exactly like a matrix transpose. I'm using python and trying using matrix transformations but I can't without loops, I'm using numpy, is there any solution just using matrix operations or vectorized functions?.
For example:
To this
Looks like you want to rotate this 180 degrees then transpose. How about:
x = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
>>> array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
np.rot90(x, 2).T
>>> array([[9, 6, 3],
[8, 5, 2],
[7, 4, 1]])
Here are is a way that only uses indexing:
>>> import numpy as np
>>> a = np.array(['abcdefghi']).view('U1').reshape(3, 3)
>>> a
array([['a', 'b', 'c'],
['d', 'e', 'f'],
['g', 'h', 'i']], dtype='<U1')
>>>
>>> a[[2,1,0],[[2],[1],[0]]]
array([['i', 'f', 'c'],
['h', 'e', 'b'],
['g', 'd', 'a']], dtype='<U1')
If you do not want to hardcode the indices you'll have to use some kind of builtin. Either Python builtins:
>>> a[list(reversed(range(3))), list(zip(reversed(range(3))))]
array([['i', 'f', 'c'],
['h', 'e', 'b'],
['g', 'd', 'a']], dtype='<U1')
or numpy
>>> a[np.ogrid[2:-1:-1,2:-1:-1][::-1]]
array([['i', 'f', 'c'],
['h', 'e', 'b'],
['g', 'd', 'a']], dtype='<U1')
Note that all these methods do a non-lazy transpose, meaning that the resulting array is C contiguous.
For example, I have a flat list
[1, 2, 3, 4, 5, 6, 7, 8, 9, 'A', 'B', 'C', 'D', 'E', 'F', 'G']
I want to transform it into 4-deep list
[[[[1, 2], [3, 4]], [[5, 6], [7, 8]]], [[[9, 'A'], ['B', 'C']], [['D', 'E'] ['F', 'G']]]]
Is there a way to do it without creating a separate variable for every level? What is the most memory- and performance-efficient way?
UPDATE:
Also, is there a way to do it in a non-symmetrical fashion?
[[[[1, 2, 3], 4], [[5, 6, 7], 8]]], [[[9, 'A', 'B'], 'C']], [['D', 'E', 'F'], 'G']]]]
Note that your first list has 15 elements instead of 16. Also, what should A be? Is it a constant you've defined somewhere else? I'll just assume it's a string : 'A'.
If you work with np.arrays, you could simply reshape your array:
import numpy as np
r = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 'A', 'B', 'C', 'D', 'E', 'F', 'G'])
r.reshape(2,2,2,2)
It outputs:
array([[[['1', '2'],
['3', '4']],
[['5', '6'],
['7', '8']]]
[[['9', 'A'],
['B', 'C']],
[['D', 'E'],
['F', 'G']]]
dtype='<U11')
This should be really efficient because numpy doesn't change the underlying data format. It's still a flat array, displayed differently.
Numpy doesn't support irregular shapes. You'll have to work with standard python lists then:
i = iter([1, 2, 3, 4, 5, 6, 7, 8, 9, 'A', 'B', 'C', 'D', 'E', 'F', 'G'])
l1 = []
for _ in range(2):
l2 = []
for _ in range(2):
l3 = []
l4 = []
for _ in range(3):
l4.append(next(i))
l3.append(l4)
l3.append(next(i))
l2.append(l3)
l1.append(l2)
print(l1)
# [[[[1, 2, 3], 4], [[5, 6, 7], 8]], [[[9, 'A', 'B'], 'C'], [['D', 'E', 'F'], 'G']]]
As you said, you'll have to define a temporary variable for each level. I guess you could use list comprehensions, but they wouldn't be pretty.
My problem is this.
These are the two lists
codes = ['a', 'b', 'c', 'a', 'e', 'f', 'g', 'a', 'i', 'j', 'a', 'l']
pas = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
How would I find the position of all the 'a' in the codes list. And then print out the corresponding item in the pas list.
This is what the output should be. They should also be sorted with the .sort() function.
1
4
8
11
I have come up with this code. (That doesnt work)
qwer = [i for i,x in enumerate(codes) if x == common]
qwe = [qwer[i:i+1] for i in range(0, len(qwer), 1)]
print(pas[qwe])
What would be the best way to get the correct output?
>>> pas = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
>>> codes = ['a', 'b', 'c', 'a', 'e', 'f', 'g', 'a', 'i', 'j', 'a', 'l']
>>> result = sorted(i for i,j in zip(pas,codes) if j=='a')
>>> for i in result:
... print i
...
1
4
8
11
There are many ways to achieve it. Your example lists are:
>>> codes = ['a', 'b', 'c', 'a', 'e', 'f', 'g', 'a', 'i', 'j', 'a', 'l']
>>> pas = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
Approach 1: Using enumerate:
>>> indices = [pas[i] for i, x in enumerate(codes) if x == "a"]
indices = [1, 4, 8, 11]
Approach 2: Using zip:
>>> [p for p, c in zip(pas, codes) if c == 'a']
[1, 4, 8, 11]
Just added another way to use numpy:
import numpy as np
codes = np.array(['a', 'b', 'c', 'a', 'e', 'f', 'g', 'a', 'i', 'j', 'a', 'l'])
pas = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])
index = np.where(codes=='a')
values = pas[index]
In [122]: print(values)
[ 1 4 8 11]
codes = ['a', 'b', 'c', 'a', 'e', 'f', 'g', 'a', 'i', 'j', 'a', 'l']
pas = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
[pas[index] for index, element in enumerate(codes) if element == "a"]
Consider the following list in python:
[[[1, 2], [3, 4], [5, 6], [7, 8]],
[['a', 'b'], ['c', 'd'], ['e', 'f'], ['g', 'h']],
[[21, 22], [23, 24], [25, 26], [27, 28]]]
The top level list contains 3 list values which in-turn consists of 4 individual lists.
I need to arrange these this lists in the following order:
[[1, 2, 'a', 'b', 21, 22],
[3, 4, 'c', 'd', 23, 24],
[5, 6, 'e', 'f', 25, 26],
[7, 8, 'g', 'h', 27, 28]]
I have tried to implement this requirement using itertools, for loops, list comprehension etc but was unable to get it. Could you provide me the necessary python code capable of doing this requirement?
You need to use zip() here, then flatten out the resulting tuples with sublists:
[[i for sub in combo for i in sub] for combo in zip(*inputlist)]
Demo:
>>> inputlist = [[[1, 2], [3, 4], [5, 6], [7, 8]],
... [['a', 'b'], ['c', 'd'], ['e', 'f'], ['g', 'h']],
... [[21, 22], [23, 24], [25, 26], [27, 28]]]
>>> [[i for sub in combo for i in sub] for combo in zip(*inputlist)]
[[1, 2, 'a', 'b', 21, 22], [3, 4, 'c', 'd', 23, 24], [5, 6, 'e', 'f', 25, 26], [7, 8, 'g', 'h', 27, 28]]
Using itertools with map:
>>> from itertools import chain, izip, starmap
>>> map(list, starmap(chain, izip(*lst)))
[[1, 2, 'a', 'b', 21, 22],
[3, 4, 'c', 'd', 23, 24],
[5, 6, 'e', 'f', 25, 26],
[7, 8, 'g', 'h', 27, 28]]