Combining two list of lists into one - python

There are two lists of lists, I need to make one list out of them.
a = [[1,2,3],[4,5,6]]
b = [[1,2,3],[4,5,6]]
I_need = [[1,1,2,2,3,3],[4,4,5,5,6,6]]
or one more question, how to duplicate the list to have the same result.
I will be glad for any help!

As you marked your question with Numpy tag, I assume that you
want to use just Numpy.
To easier tell apart elements of both source arrays, I defined them as:
a = [[ 1, 2, 3],[ 4, 5, 6]]
b = [[10,20,30],[40,50,60]]
To get your expected result, run:
result = np.dstack([a, b]).reshape(2, -1)
The result is:
array([[ 1, 10, 2, 20, 3, 30],
[ 4, 40, 5, 50, 6, 60]])
If you want a plain pythonic list (instead of a Numpy array),
append .tolist() to your code.

If you have python lists:
I_need = [[e for x in zip(*l) for e in x] for l in zip(a,b)]
output: [[1, 1, 2, 2, 3, 3], [4, 4, 5, 5, 6, 6]]
If you have numpy arrays:
a = np.array([[1,2,3],[4,5,6]])
b = np.array([[1,2,3],[4,5,6]])
I_need = np.c_[a.ravel(), b.ravel()].reshape(2,-1)
output:
array([[1, 1, 2, 2, 3, 3],
[4, 4, 5, 5, 6, 6]])

Related

Python - delete columns in 2D list

I have a 2D list = [[1, 8, 3], [4, 5, 6], [0, 5, 7]], and I want to delete columns in a loop.
For example, columns with index: 0(first) and 2(last) - - the result after deletions should be: [8, 5, 5].
There is a problem, because when I delete the 0th column, the size of the list is decreased to (0,1), and the 2nd index is out of scope.
What is the fastest method to delete columns in a loop without the out-of-scope problem?
For a better picture:
[[1, 8, 3],
[4, 5, 6],
[0, 5, 7]]
There is no such shortcut in python except for iterating over all the list items and removing those index values.
However, you can use pandas which is meant for some other purpose but will do the task.
import pandas as pd
s = [[1, 8, 3], [4, 5, 6], [0, 5, 7]]
df = pd.DataFrame(s,columns=['val1','val2','val3'])
li = df.drop('val1',axis=1).values.tolist()
now li will look like this
[[8, 3], [5, 6], [5, 7]]
You can use numpy like this:
import numpy as np
my_list = np.array([[1, 8, 3], [4, 5, 6], [0, 5, 7]])
new_list = my_list[:, 1].copy()
print(new_list)
Output:
>>> [8, 5, 5]
Also numpy.delete(your_list, index, axis) is do the same job:
new_list = np.delete(my_list,(0, 2), axis=1)
(0, 2) is the indices of the columns 0 and 2
axis=1 says numpy that (0, 2) are columns indices not rows.
if you want to delete rows 0 and 2 you can change axis=1 to axis=0
Output is a little different:
>>> array([[8],
[5],
[5]])
For a pure python approach:
my_list = [[1, 8, 3], [4, 5, 6], [0, 5, 7]]
new_list = [value[1] for value in my_list]
print(new_list)
Output:
>>> [8, 5, 5]
L is 2D list:
print(map(lambda x: x[1:], L))
data= [[1, 8, 3], [4, 5, 6], [0, 5, 7]]
index_to_remove=[0,2]
[list(x) for x in zip(*[d for i,d in enumerate(zip(*data)) if i not in index_to_remove])]
If I understood your question correctly, you want to keep the middle element (index 1) of each list,in that case I would suggest creating a new list. There could be other better ways, for sure. But you could try this, if this works for you:
twoD_list = [[1, 8, 3], [4, 5, 6], [0, 5, 7]]
def keep_col( twoD_list ,index_to_keep = 1):
final_list = []
for x in twoD_list:
final_list.append(x[index_to_keep])
return final_list
final_list = keep_col( twoD_list , 1)
Final output:
[8,5,5]
Assuming you always want only the second element and the inner lists always have at least two elements.
Pure python with list comprehension:
lst = [
[1, 8, 3],
[4, 5, 6],
[0, 5, 7],
]
filtered_lst = [
inner_element
for inner_lst in lst
for i, inner_element in enumerate(inner_lst)
if i == 1
]
print(filtered_lst)
# [8, 5, 5]
If you want you can the reassign the new list to the old variable:
lst = filtered_lst
The advantages of this method are:
no need to worry about the list being altered while you iterate it,
no need to import other libraries
list comprehension is built-in
list comprehension is often the fastest way to filter a list (see for example this article)
easier to read and maintain that other solutions (in my opinion).
Via itemgetter to extract the value at index 1.
from operator import itemgetter
my_list = [[1, 8, 3], [4, 5, 6], [0, 5, 7]]
result = list(map(itemgetter(1), my_list))
try this
my_list = [[1, 8, 3], [4, 5, 6], [0, 5, 7]]
filter_col=[0,2]
col_length=3
my_list=[[x[i] for i in range(col_length) if i not in filter_col] for x in my_list]
u do not want to directly mutate the list that you are working on
this performs a list comprehension to create a new list from the existing list
edit:
just saw u wanted only a flat list
assuming u only want one element for the list u can use
my_list=[x[1] for x in my_list]

How to split a numpy array based on a tuple content? [duplicate]

This question already has an answer here:
Create index list for np.split from the list that already has number for each section
(1 answer)
Closed 3 years ago.
Let's say I've got an array [0, 1, 2, 3, 4, 5, 6, 7] and a tuple: (3, 3, 2).
I'm looking for a way to split my array to 3 array based on my tuple data:
[0, 1, 2]
[3, 4, 5]
[6, 7]
I can write a simple code like this to get what I want, however I'm looking for a correct and pythonic way to do this:
I used lists for simplicity.
a = [0, 1, 2, 3, 4, 5, 6, 7]
b = (3, 3, 2)
pointer = 0
for i in b:
lst = []
for j in range(i):
lst.append(a[pointer])
pointer += 1
print(lst)
Or this one:
a = [0, 1, 2, 3, 4, 5, 6, 7]
b = (3, 3, 2)
pointer = 0
for i in b:
lst = a[pointer:pointer+i]
pointer += i
print(lst)
Results:
[0, 1, 2]
[3, 4, 5]
[6, 7]
you can use the split method of numpy
import numpy as np
a = [0, 1, 2, 3, 4, 5, 6, 7]
b = (3, 3, 2)
c = np.split(a, np.cumsum(b)[:-1])
for r in c:
print(r)
np.split(a, b) splits a by the indices in b along a given axis(0 by default).
If you don't want to modify your input list, you can use an iterator and the itertools module.
>>> from itertools import islice
>>> a = [0, 1, 2, 3, 4, 5, 6, 7]
>>> b = (3, 3, 2)
>>> i = iter(a)
>>> [list(islice(i, x)) for x in b]
[[0, 1, 2], [3, 4, 5], [6, 7]]
In the first step you create an iterator, which starts at the first element of a. Then you iterate in a list comprehension over your numbers in b and in each step you pull accordingly many elements from the iterator and store them in your result list.
One simpler way is this:
a = [0, 1, 2, 3, 4, 5, 6, 7]
b = (3, 3, 2)
for ind in b:
print(a[:ind])
a = a[ind:]
It loops through slice sizes in b while shortening the original array every time. You can easily append the resulting slices as sublists if you need them for something else. It's almost like one of your solutions except it doesn't use any extra variables and iterates directly through elements of b.
Also, I wouldn't call variables a and b - surely not in this case where variables have clear meanings that you can express through their names. More meaningful names lessen bugs number and make code more clear, becomes a real difference with larger/more complex code. I'd call a at least in_list and b slices, but with more context this could be better.
The most "concise" syntax would be :
ex_array = [0, 1, 2, 3, 4, 5, 6, 7]
extuple = (3, 3, 2)
result = [ex_array[sum(extuple[:iii]):sum(extuple[:iii])+extuple[iii]] for iii in range(len(extuple))]
result would be a list of the expected sub-lists
Re-using the pairwise function from Compare two adjacent elements in same list, you could also:
from itertools import accumulate
from more_itertools import pairwise
a = [0, 1, 2, 3, 4, 5, 6, 7]
b = (3, 3, 2)
[a[slice(*s)] for s in pairwise(accumulate((0,)+b))]
That begin said, the np.split answer is probably faster (and easier to read).

How can I split a list into a list of lists based on the difference between adjacent elements?

E.g., if I've got
MAX_ALLOWED_DIFF = 3
nums=[1, 2, 4, 10, 13, 2, 5, 5, 5]
the output should be
groups = [[1, 2, 4], [10, 13], [2, 5, 5, 5]]
The context: I had a pandas.Series object nums and I used
nums = nums.diff().gt(DETECTION_MAX_DIFF_NS).cumsum()).apply(list).tolist()
to subsample in the same fashion but I noticed that there're a lot of duplicates in my Series nums and after I use .unique() method I don't have Series object anymore, I've got numpy.ndarray (1D) instead.
I believe I may use sth like pandas.Series(nums.unique) but I don't like this hack.
So we using drop_duplicates, keep nums stay in pd.Series
nums=nums.drop_duplicates()
nums.groupby(nums.diff().abs().gt(MAX_ALLOWED_DIFF).cumsum()).apply(list).tolist()
Out[447]: [[1, 2, 4], [10, 13], [5]]
Here's one approach -
>>> import numpy as np
>>> idx = np.r_[0,np.flatnonzero(np.abs(np.diff(nums))>MAX_ALLOWED_DIFF)+1,len(nums)]
>>> [nums[i:j] for (i,j) in zip(idx[:-1],idx[1:])]
[[1, 2, 4], [10, 13], [2, 5, 5, 5]]
Given that you've tagged with numpy too, here's one way to do it:
thr = 3
ix = np.flatnonzero(np.concatenate([[False], np.abs(np.diff(nums))>thr]))
np.split(nums, ix)
Output
[array([1, 2, 4]), array([10, 13]), array([2, 5, 5, 5])]

Need to convert 3d array to 2d with mean of inner array

I am receiving a output like the below:
y = [[[1,1,1,1,1,1,1] ,[2,2,2,2,2,2,2], [3,3,3,3,3,3,3]],[[4,4,4],[5, 5, 5],[6, 6, 6]]]
the final output should be as below:
Y = [[1, 2, 3], [4, 5, 6]]
How to convert y to Y? [Here, the mean of the innermost array (or optionally any element) need to be used as a basic element and the final array (Y) need to be 2D, whereas the pre-final array (y) is 3D.
(I am new to numpy/python, so this question my look stupid, if any other information is needed, please let me know)
Try this,
result = []
for i in lst:
result.append([j[0] for j in i])
print result
Result
[[1, 2, 3], [4, 5, 6]]
With list comprehension:
y = [[[1,1,1,1,1,1,1] ,[2,2,2,2,2,2,2], [3,3,3,3,3,3,3]],[[4,4,4],[5, 5, 5],[6, 6, 6]]]
Y = [[x[0] for x in z] for z in y] # [[1, 2, 3], [4, 5, 6]]
double loops and insert will do the trick
import numpy as np
y = [[[1, 1, 1, 1, 1, 1, 1 ], [2, 2, 2, 2, 2, 2, 2 ] ,[3, 3, 3, 3, 3, 3, 3]],[[4, 4, 4],[5, 5, 5],[6, 6, 6]]]
Y = []
for l in y:
inner_l = []
for sub_l in l :
inner_l.append(np.mean(sub_l))
Y.append(inner_l)
print Y
y=[[[1,1,1,1,1,1,1] ,[2,2,2,2,2,2,2], [3,3,3,3,3,3,3]],[[4,4,4],[5, 5, 5],[6, 6, 6]]]
rslt = []
for x in y:
lst=[]
for m in x:
lst.append([m[0]])
rslt.append(lst)
Result:
rslt = [[1, 2, 3], [4, 5, 6]]

Finding the index of the minimum of each list in a list of lists

I'm trying to create a list of the index's of the minimums of each list in a list of list. I have only been able to find an answer for a simple list.
data = [[9 ,5, 2, 8, 6], [3, 5, 1, 9, 2], [2, 9, 3, 0, 5]]
My first idea was to use
.index(min(n))
but it doesn't work for a list of lists.
Expected result:
new_list = [2, 2, 3]
use a list comprehension:
[x.index(min(x)) for x in data]
>>>data = [[9 ,5, 2, 8, 6], [3, 5, 1, 9, 2], [2, 9, 3, 0, 5]]
>>>[x.index(min(x))+1 for x in data]
[3, 3, 4] //actual index (Your required output)
Try it:
result = []
for list in data:
result.append(list.index(min(list)))
At the same time, the answer what you want to get is [2,2,3], not [3,3,4]. Because the list's index start from 0. I hope this can help you.

Categories

Resources