I want to "set" the values of a row of a Python nested list to another row without using NumPy.
I have a sample list:
lst = [[0, 0, 1],
[0, 2, 3],
[5, 2, 3]]
I want to make row 1 to row 2, row 2 to row 3, and row 3 to row 1. My desired output is:
lst = [[0, 2, 3],
[5, 2, 3],
[0, 0, 1]]
How can I do this without using Numpy?
I tried to do something like arr[[0, 1]] = arr[[1, 0]] but it gives the error 'NoneType' object is not subscriptable.
One very straightforward way:
arr = [arr[-1], *arr[:-1]]
Or another way to achieve the same:
arr = [arr[-1]] + arr[:-1]
arr[-1] is the last element of the array. And arr[:-1] is everything up to the last element of the array.
The first solution builds a new list and adds the last element first and then all the other elements. The second one constructs a list with only the last element and then extends it with the list containing the rest.
Note: naming your list an array doesn't make it one. Although you can access a list of lists like arr[i1][i2], it's still just a list of lists. Look at the array documentation for Python's actual array.
The solution user #MadPhysicist provided comes down to the second solution provided here, since [arr[-1]] == arr[-1:]
Since python does not actually support multidimensional lists, your task becomes simpler by virtue of the fact that you are dealing with a list containing lists of rows.
To roll the list, just reassemble the outer container:
result = lst[-1:] + lst[:-1]
Numpy has a special interpretation for lists of integers, like [0, 1], tuples, like :, -1, single integers, and slices. Python lists only understand single integers and slices as indices, and do not accept tuples as multidimensional indices, because, again, lists are fundamentally one-dimensional.
use this generalisation
arr = [arr[-1]] + arr[:-1]
which according to your example means
arr[0],arr[1],arr[2] = arr[1],arr[2],arr[0]
or
arr = [arr[2]]+arr[:2]
or
arr = [arr[2]]+arr[:-1]
You can use this
>>> lst = [[0, 0, 1],
[0, 2, 3],
[5, 2, 3]]
>>> lst = [*lst[1:], *lst[:1]]
>>>lst
[[0, 2, 3],
[5, 2, 3],
[0, 0, 1]]
Related
I am learning numpy newly and confused about syntax used in indexing of arrays. For example:
arr[2, 3]
This means element at intersection of 3nd row and 4th column. What confuses me separation of different indices by comma inside square brackets (like in function arguments). Doing so with python lists is not valid:
l = [[1, 2], [3, 4]]
l[1, 1]
Traceback (most recent call last):
File "", line 1, in
TypeError: list indices must be integers or slices, not tuple
So, if this not a valid python syntax, how numpy arrays work?
Use Colon ':' instead of commas ','.
In slicing or indexing is done using colon ':'
In your above example,
l = [[1, 2], [3, 4]]
->l[0] is [1,2] and -> l[1] is [3,4]
Read further documentation for better understanding.
Thank You
In your given example, you're comparing a numpy array to a list of lists. The main difference between the two is that a numpy array is predictable in terms of shape, data type of its elements, and so on, while a list can contain an arbitrary combination of any other python objects (lists, tuples, strings, etc.)
Take this as an example, say you create a numpy array like so:
arr = np.array([[0, 1], [2, 3], [4, 5]])
Here, the shape of arr is known right after instantiation "arr.shape returns (3,2)", so you can easily index the array with only a comma separated square bracket. On the other hand, take the list example:
l = [[0, 1], [2, 3], [4, 5]]
l[0] # This returns the list [0, 1]
l[0].append("HELLO")
l[0] # This returns the list [0, 1, "HELLO"]
A list is very unpredictable, as there's no way to know what each list element will return to you. So, the way we index a specific element in a list of lists is by using 2 square brackets "e.g. l[0][0]"
What if we created a non-uniform numpy array? Well, you get a similar behaviour to a list of lists:
arr = np.array([[0, 1], [2, 3], [4]]) # Here, you get a Warning!
print(arr) # Returns: array([list([0, 1]), list([2, 3]), list([4])], dtype=object)
In this case, you can't index the numpy array using [0, 0]. Instead, you have to use two square brackets, just like a list of lists
You can also check the documentation of ndarray for more info.
So, say I have the following list and variable i:
data = [ [1, 2, 3, 1, 1], [1, 2, 3, 0, 0], [1, 2, 3, 2, 1] ]
i = 3
I would like to create a new list which will sum together and merge numbers from each sublist the ith element upwards to produce the following:
new_data = [ [1, 2, 5], [1, 2, 3], [1, 2, 6] ]
Where I have summed from each sublist the 3rd element upwards and merged the elements together. I would like to ask how, by using the standard library in Python, I can go about achieving this for an arbitrary (integer) value of i. I have the following idea in mind but I'm not sure how to put it into real Python code:
(pseudo-code)
new_data = []
for sublist in data:
new_data.append(elements before the ith element)
new_data.append(ith element onwards summed together)
You can slice your inner list by index and sum the rest with the one-liner:
>>> new_data = [row[:i-1] + [sum(row[i-1:])] for row in data]
>>> new_data
[[1, 2, 5], [1, 2, 5], [1, 2, 5]]
You can find a nice, "pythonic" one-liner in taras' answer:
new_data = [row[:i-1] + [sum(row[i-1:])] for row in data].
From pseudo-code to correct python code
I'll focus my answer on helping you transform your pseudo-code into python code.
Pseudo-code:
new_data = []
for sublist in data:
new_data.append(elements before the ith element)
new_data.append(ith element onwards summed together)
The first issue with your pseudo-code is that you are making a distinction between the list data and its sublists sublist, but you are not making a distinction between the list new_data and its sublists. Let me add a variable new_sublist in the loop:
new_data = []
for sublist in data:
new_sublist = []
new_sublist.append(elements before the ith element)
new_sublist.append(ith element onwards summed together)
new_data.append(new_sublist)
The second issue with your pseudo code: you make two calls to .append in each iteration of the loop. However, these two calls are not similar: the first call is supposed to append several elements, whereas the second call is supposed to append one element. Python makes a distinction between the two operations; if you want to add more than one element at once, use .extend instead of .append. The code becomes:
new_data = []
for sublist in data:
new_sublist = []
new_sublist.extend([elements before the ith element])
new_sublist.append(ith element onwards summed together)
new_data.append(new_sublist)
Finally we can turn your pseudo-code into proper python code, using a list slice to get the elements before the ith element, and builtin function sum along with a list slice to sum the ith element onwards:
new_data = []
for sublist in data:
new_sublist = []
new_sublist.extend(sublist[:i])
new_sublist.append(sum(sublist[i:]))
new_data.append(new_sublist)
Note that in python, looping over a list to construct a new list is such a common operation that we use the compact and elegant list comprehension syntax to do it instead of a multiline for-loop:
new_data = [sublist[:i] + [sum(sublist[i:])] for sublist in data]
Relevant documentation
list.extend and list.append;
list slices;
builtin function sum;
list comprehensions.
You can do it like so:
def merger(data, pos):
pos -= 1 # 0 based, your i above is 1 based
# collection list for result
result = []
# go over each given inner part
for inner in data:
# add it up to the correct position
result.append(inner[:pos])
# extend it by the sum of the remainder values
result[-1].append(sum(inner[pos:]))
return result
data = [ [1, 2, 3, 1, 1], [1, 2, 3, 1, 1], [1, 2, 3, 1, 1] ]
i = 3
print(merger(data,i))
Output:
[[1, 2, 5], [1, 2, 5], [1, 2, 5]]
or in short:
def merger(data, pos):
return [[inner[: pos - 1] + [sum(inner[pos - 1 :])] for inner in data]]
data = [ [1, 2, 3, 1, 1], [1, 2, 3, 1, 1], [1, 2, 3, 1, 1] ]
i = 3
new_data = [sublist[:i-1] + [sum(sublist[i-1:])] for sublist in data]
print(new_data)
>>> [[1, 2, 5], [1, 2, 5], [1, 2, 5]]
I'm a newbie on Python, and am struggling with a small piece of my code I just don't understand why it won't work.
I have list of lists, containing 3 numbers each. I want to check if the first two numbers are the same for some of the lists. Why doesn't this work? What should I do to get it work?
list=[[0, 4, 0], [1, 4, 0], [0, 3, 1], [0, 4, 1]]
sorted(list)
for i in range(len(list)-1):
if list[i][0][1] == list[i+1][0][1]:
print "overlap"
You are trying to access your matrix as if it would be a 3-dimensional matrix, however it's a 2-dimensional matrix.
Remove one of the indexes:
list=[[0, 4, 0], [1, 4, 0], [0, 3, 1], [0, 4, 1]]
sorted(list)
for i in range(len(list)-1):
if list[i][0:2] == list[i + 1][0:2]:
print "overlap"
As #Dunes pointed out, the slice operator allows you to compare the required items of your list (check out understanding python slice notation for details).
You don't need that extra [1].
list[i] accesses the inner list, e.g. [0, 4, 0]
list[i][0] accesses the 1st element of that list: e.g. 0
Also, please don't use built-in names as names for your variables as the built-in (list in our case) will no longer be accessible by that name.
I tried to remove only one element from an array and print remaining ones in a loop:
arr = [1,2,3,4,5]
for i in arr:
a = arr
a.remove(i)
print a
So I am expecting it to print this:
[2, 3, 4, 5]
[1, 3, 4, 5]
[1, 2, 3, 5]
[1, 2, 3, 4]
Why am I gettting the following results instead:
[2, 3, 4, 5]
[2, 4, 5]
[2, 4]
This is a classic problem of deep vs shallow copy.
Python copies the array by reference. So, any changes to the new variable (a in your case) will be reflected in the main array (arr). Removing element from a also remove elements from arr.
You need to use following for creating a copy.
a = arr[:]
This will not remove any elements from arr.
You've already got explanations, I'll provide an alternative - you can produce requested output without using remove at all:
arr = [1,2,3,4,5]
for i in arr:
a = [x for x in arr if x != i]
print a
(beware of non-unique elements in arr, if there are any, both this code and yours will produce unexpected results, though in different ways).
You can try this.
arr = [1, 2, 3, 4, 5, 6, 7 ]
for index, item in enumerate(arr):
print(arr[0:index] + arr[index+1:])
I think this can help you.
If you don't have any repeated value you can use this too.
for item in arr:
print(set(arr) - set([item]))
Python lists are mutable i.e. modifying operations (like list.remove()) on them do not produce a new list but modify the existing list instead so each your cycle actually permanently modifies the source list and elements are lost. You'd need to copy your whole list each time you want to modify it in order to achieve what you want, or you can create a new list with elements excluded, or, for very long lists, reconstructing by slicing is probably the most performant way:
arr = [1,2,3,4,5]
for i in range(len(arr)):
a = arr[0:i] + arr[i+1:]
print(a)
I have a quite involved nested list: each element is a tuple with two elements: one is an object, the other is an 3x2xn array. Here is a toy model.
toy=[('mol1',array([[[1,1,1],[2,2,2]],[[1,1,1],[2,2,2]]])),('mol2',array([[[1,1,1],[2,2,2]],[[1,1,1],[2,2,2]]]))]
How can I get a single column from that?
I am looking for
('mol1', 'mol2')
and for the 2Darrays like:
array([[1,1,1],[1,1,1],[1,1,1],[1,1,1]])
I have a solution but I think it is pretty inefficient:
zip(*toy)[0]
it returns
('mol1', 'mol2')
then
zip(*toy)[1][0][:,0]
which returns
array([[1, 1, 1],
[1, 1, 1]])
a for cycle like that
for i in range(len(toy)):
zip(*toy)[1][i][:,0]
gives all the element of the column and I can build it with a vstack
This should be reasonably efficient:
>>> tuple(t[0] for t in toy)
('mol1', 'mol2')
For the 2D array, with the help of numpy's vstack function:
>>> from numpy import vstack
>>> vstack([t[1][:, 0] for t in toy])
array([[1, 1, 1],
[1, 1, 1],
[1, 1, 1],
[1, 1, 1]])
You can use the array in numpy to store your data or convert yours to that, then use the column slicing function built in. In general numpy slicing is very fast.
import numpy as np
np.asarray(toy)[::, 0] # first column
# output
array(['mol1', 'mol2'],
dtype='|S4')