How to insert number in 2d list? - python

How can I insert a value, here 99, into the indices 1 producing [3,4,99] ?
x=[[1,2],[3,4],[5,6]]
x.insert(1[1],99) #this gives back 'int' object is not subscriptable
print(x)

Append the element to the list element index 1 with x[1].append(99).
>>> x=[[1,2],[3,4],[5,6]]
>>> x[1].append(99)
>>> print(x)
[[1, 2], [3, 4, 99], [5, 6]]

given the list:
x=[[1,2],[3,4],[5,6]]
if you want to insert an element in the middle of the [3,4] element:
x[1].insert(1, 3.5)
will return you
>>> x
[[1, 2], [3, 3.5, 4], [5, 6]]
if you want to add anything to the end of a list, the method for that is append:
x[1].append(5)
now you have:
>>> x
[[1, 2], [3, 3.5, 4, 5], [5, 6]]

Related

Python casting leads to weird mutability result

Why is it that when I write the code block as:
def rev(li):
li.reverse()
l = [[1, 2, 3], [4, 5, 6]]
map(rev, l)
print(l)
The resulting list is the same as the original list, but when I rewrite the code to now cast the map object into a list as such:
def rev(li):
li.reverse()
l = [[1, 2, 3], [4, 5, 6]]
list(map(rev, l))
print(l)
It does reverse the inner lists to give me [[3, 2, 1], [6, 5, 4]]. How does casting the map object to a list change mutability rules for the list l?

How to filter out equivalent lists of values in python?

When given a list of lists like: [[5, 2] [2, 5]]
I want to reduce this list to this: [[5, 2]] or [[2, 5]]
I've already tried the following: list(map(list, set(map(frozenset, parts_to_add))))
But the problem with this method is that it turns my lists in sets and while this works - it filters out all the equivalent lists - it also eats all of my duplicate values; When given [[3, 3]] it returns [[3]], due to the nature of sets in python. Is there another way of doing this?
Any help would be grately appreciated.
You could do :
data = [[5, 2], [2, 5], [3, 3]]
result = set(tuple(e) for e in map(sorted, data))
print([list(e) for e in result])
Output
[[2, 5], [3, 3]]
As #soon mentioned you could use a frozen Counter, for example:
from collections import Counter
data = [[5, 2], [2, 5], [3, 3]]
result = [e for e in {frozenset(Counter(e)): e for e in data}.values()]
print(result)
Output
[[2, 5], [3, 3]]
The above approach also uses a dict for removing duplicates instead of a set.
A more straightforward approach would be,
data = [[2, 5], [5, 2], [3, 6], [2, 5], [6, 3]]
result = []
for i in range(len(data)):
data[i].sort()
if data[i] not in result:
result.append(data[i])
In [49]: result
Out[49]: [[2, 5], [3, 6]]

How to do Math Functions on Lists within a List

I'm very new to python (using python3) and I'm trying to add numbers from one list to another list. The only problem is that the second list is a list of lists. For example:
[[1, 2, 3], [4, 5, 6]]
What I want is to, say, add 1 to each item in the first list and 2 to each item in the second, returning something like this:
[[2, 3, 4], [6, 7, 8]]
I tried this:
original_lst = [[1, 2, 3], [4, 5, 6]]
trasposition_lst = [1, 2]
new_lst = [x+y for x,y in zip(original_lst, transposition_ls)]
print(new_lst)
When I do this, I get an error
can only concatenate list (not "int") to list
This leads me to believe that I can't operate in this way on the lists as long as they are nested within another list. I want to do this operation without flattening the nested list. Is there a solution?
One approach using enumerate
Demo:
l = [[1, 2, 3], [4, 5, 6]]
print( [[j+i for j in v] for i,v in enumerate(l, 1)] )
Output:
[[2, 3, 4], [6, 7, 8]]
You can use enumerate:
l = [[1, 2, 3], [4, 5, 6]]
new_l = [[c+i for c in a] for i, a in enumerate(l, 1)]
Output:
[[2, 3, 4], [6, 7, 8]]
Why don't use numpy instead?
import numpy as np
mat = np.array([[1, 2, 3], [4, 5, 6]])
mul = np.array([1,2])
m = np.ones(mat.shape)
res = (m.T *mul).T + mat
You were very close with you original method. Just fell one step short.
Small addition
original_lst = [[1, 2, 3], [4, 5, 6]]
transposition_lst = [1, 2]
new_lst = [[xx + y for xx in x] for x, y in zip(original_lst, transposition_lst)]
print(new_lst)
Output
[[2, 3, 4], [6, 7, 8]]
Reasoning
If you print your original zip it is easy to see the issue. Your original zip yielded this:
In:
original_lst = [[1, 2, 3], [4, 5, 6]]
transposition_lst = [1, 2]
for x,y in zip(original_lst, transposition_lst):
print(x, y)
Output
[1, 2, 3] 1
[4, 5, 6] 2
Now it is easy to see that you are trying to add an integer to a list (hence the error). Which python doesn't understand. if they were both integers it would add them or if they were both lists it would combine them.
To fix this you need to do one extra step with your code to add the integer to each value in the list. Hence the addition of the extra list comprehension in the solution above.
A different approach than numpy that could work even for lists of different lengths is
lst = [[1, 2, 3], [4, 5, 6, 7]]
c = [1, 2]
res = [[l + c[i] for l in lst[i]] for i in range(len(c))]

Convert a dict to numpy multi-dimensional array

I have a python dictionary defined as follows, where the innermost items are two-element array:
mydict = {1: {1: [1, 2], 2: [3, 4]}, 2: {1: [5, 6], 2: [7, 8]}}
What I need now is to form all the 0th elements as a new array, i.e., using a[:,:,0] or a[...,0] to return [1,3,5,6]. However, a[:,:,0] or a[...,0] would not work in this case as shown below.
import numpy as np
import pandas as pd
a = np.array(pd.DataFrame.from_dict(mydict))
print a
which gives the following output:
[[[1, 2] [5, 6]]
[[3, 4] [7, 8]]]
It seems that this is an 2x2x2 array. There is no problem with accessing the corresponding element using separate brackets, e.g., a[0][0][0] returns 1. However, a[0,0,0] would cause an error.
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
<ipython-input-150-f68aba7de42a> in <module>()
----> 1 a[0,0,0]
IndexError: too many indices for array
It seems that the two-element arrays are considered as elements in the 2x2 array -- but what I need is a 2x2x2 array in order to achieve my goal. Is there any way to convert this to a 2x2x2 array?
Your issue comes from the fact that pandas is treating your initial entries (lists) as objects, so then when you convert to a numpy array, your inner most entries are list objects. For example,
> type(a)
numpy.ndarray
> type(a[0])
numpy.ndarray
> type(a[0,0])
list
If you know the shape you ultimately want (2x2x2), you could always do:
> b = np.array(map(np.array, a.flat)).reshape(2,2,2)
> b.shape
(2, 2, 2)
> b[0,0,0]
1
Edit: Or even simpler:
> b = np.array(a.tolist())
array([[[1, 2],
[5, 6]],
[[3, 4],
[7, 8]]])
If you want the first item of each innermost row, e.g. 1,3,5,7, you could do b[...,0] or b[...,0].flatten() depending on the resulting shape you want.
Without Pandas I can recreate your array with:
In [1723]: mydict = {1: {1: [1, 2], 2: [3, 4]}, 2: {1: [5, 6], 2: [7, 8]}}
In [1724]: mydict
Out[1724]: {1: {1: [1, 2], 2: [3, 4]}, 2: {1: [5, 6], 2: [7, 8]}}
In [1725]: mydict[1]
Out[1725]: {1: [1, 2], 2: [3, 4]}
In [1726]: mydict[2]
Out[1726]: {1: [5, 6], 2: [7, 8]}
In [1727]: a=np.empty((2,2),dtype=object)
In [1728]: for i in range(2):
...: for j in range(2):
...: a[i,j]=mydict[i+1][j+1]
...:
In [1729]: a
Out[1729]:
array([[[1, 2], [3, 4]],
[[5, 6], [7, 8]]], dtype=object)
In [1730]: print(a)
[[[1, 2] [3, 4]]
[[5, 6] [7, 8]]]
This last print is the same as yours.
Elements of this array are lists
In [1735]: a[0,1]
Out[1735]: [3, 4]
In [1736]: type(a[0,1])
Out[1736]: list
The easist way to turn this into a 3d array is with tolist:
In [1737]: a.tolist()
Out[1737]: [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]
In [1738]: np.array(a.tolist())
Out[1738]:
array([[[1, 2],
[3, 4]],
[[5, 6],
[7, 8]]])
In [1739]: _.shape
Out[1739]: (2, 2, 2)
# dtype('int32')
tolist unpacks the array into a nested list; np.array then creates the highest-dimension array it can from that list structure.
You need to dig into each dictionary element, and then into each sub-dictionary, and pull out the first element of each of the leaf lists.
a = [mydict[x][y][0] for y in mydict[x] for x in mydict]
Result as a Python list:
[1, 3, 5, 7]
I believe this is what you actually want.

Printing a column of a 2-D List in Python

Suppose if A = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
Then A[0][:] prints [1, 2, 3]
But why does A[:][0] print [1, 2, 3] again ?
It should print the column [1, 4, 7], shouldn't it?
[:] is equivalent to copy.
A[:][0] is the first row of a copy of A.
A[0][:] is a copy of the first row of A.
The two are the same.
To get the first column: [a[0] for a in A]
Or use numpy and np.array(A)[:,0]
When you don't specify a start or end index Python returns the entire array:
A[:] = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
[:] matches the entire list.
So A[:] is the same as A. So A[0][:] is the same as A[0].
And A[0][:] is the same as A[0].
A[:] returns a copy of the entire list. which is A = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
A[:][0] Thus selects [1, 2, 3].
If you want the first column, do a loop:
col = []
for row in A:
col.append(row[0])
A is actually a list of list, not a matrix. With A[:][0] You are accessing the first element (the list [1,2,3]) of the full slice of the list A. The [:] is Python slice notation (explained in the relevant Stack Overflow question).
To get [1,4,7] you would have to use something like [sublist[0] for sublist in A], which is a list comprehension, a vital element of the Python language.
Note that [:] just gives you a copy of all the content of the list. So what you are getting is perfectly normal. I think you wanted to use this operator as you would in numpy or Matlab. This does not do the same in regular Python.
A[0] is [1, 2, 3]
Therefore A[0][:] is also [1, 2, 3]
A[:] is [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
Therefore A[:][0] is [1, 2, 3]
If you wanted the first column you should try:
[e[0] for e in A]
# [1, 4, 7]
Problem
A is not a 2-D list: it is a list of lists. In consideration of that:
A[0] is the first list in A:
>>> A = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
>>> A[0]
[1, 2, 3]
Consequently, A[0][:]: is every element of the first list:
>>> A[0][:]
[1, 2, 3]
A[:] is every element of A, in other words it is a copy of A:
>>> A[:]
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
Consequently, A[:][0] is the first element of that copy of A.
>>> A[:][0]
[1, 2, 3]
Solution
To get what you want, use numpy:
>>> import numpy as np
>>> A = np.array( [[1, 2, 3], [4, 5, 6], [7, 8, 9]] )
A is now a true two-dimensional array. We can get the first row of A:
>>> A[0,:]
array([1, 2, 3])
We can similarly get the first column of A:
>>> A[:,0]
array([1, 4, 7])
`

Categories

Resources