Let's say I have an array
a = np.array[5, 3, 2]
and based on that array I want to return a new array in the form:
b = np.array[ [0, 1, 2, 3, 4], [0, 1, 2], [0, 1] ]
I've been trying:
for item in a:
b = np.hstack(np.arange(item))
print b
but this only gives me the elements without joining them into an array;
for item in a:
b = b.append((b[:], b[item]))
print b
but this approach blows up nicely with a:
AttributeError: 'numpy.ndarray' object has no attribute 'append'
I have tried other things, like:
b[item] = np.arange(item),
but that one complains about out-of-bounds indices.
And
b = np.zeros(len(a))
for item in np.arange(len(a)):
b[item] = np.arange(b[item])
print b
which complains with
ValueError: setting an array element with a sequence.
That last one is the one that looks more promising and, searching for some questions on this site (https://stackoverflow.com/a/13311979/531687) I know that the problem is that I am trying to fit a sequence where a value is expected, but I can't figure out my way around it.
How can I go about this?
This should work
b = [range(x) for x in a]
update
The brackets [...] here create a list and inside an iterator can be used to define the items in the list. In this case the items of of type range(x) for each item in a.
Note that there is a difference in implementation between python2 and python3 here. In python2 this actually generates a list of lists. In python3 however this generates a lists of generators (the python2 equivalent would be xrange), which is typically more efficient.
Related
I am trying to find first_row = [1, 2, 3, 4, ...]
Currently, I have list = [[1, a], [2, b], [3, c], [4, d], ...]
and tried running: list[:, 0]
Output error: TypeError: List indices must be integer must be integer, not tuple
The subscript lst[:,0] does not do what you think it does. You might be used to pandas or other libraries which support indexing in multidimensional matrices, but the builtin list does not support this.
Instead, you should use a list-comprehension.
first_row = [column[0] for column in lst]
This is a shorthand for the following more verbose expression.
first_row = []
for column in lst:
first_row.append(lst[0])
In other words, you cannot vectorize multi-indexing with the list type. You have to recover each column one by one and the first element of each of those independently.
As a sidenote, try avoiding calling you variables list as it shadows the builtin of the same name.
list doesn't support multiple (i.e. "comma-separated") indices, so you need something like
[sublist[0] for sublist in list]
The most popular alternative supporting multiple indexing like you tried is numpy's multidimensional array
The reason why list cannot do this is because it is a general container, so it cannot imply what you store inside. You might have
values = [[1, 2], 'three', MyClass(4, 5, 6), None]
Applying [0, :] to this would make no sense, the same way as it doesn't in most cases.
first_row = [i[0] for i in list]
Edit:
Since there are already two answers as this one, let me show a different one if you want to use slicing. First of all you SHOULDN'T use list as the name of your variable, since list is a reserved word in python. Suppose your list is called list1, you can do:
first_row = list(np.array(list1)[0,:].astype(int))
I've had a look through the forums and can't find anything to do with multiplying all elements in an array recursively.
I've created the following code that almost does what I want. The goal is to use no loops and only recursion.
Here's the code:
def multAll(k,A):
multAllAux(k,A)
return A[:]
def multAllAux(k,A):
B = [0]
if A == []:
return 0
else:
B[0] = (A[0] * k)
B.append(multAllAux(k,A[1:]))
return B
print(multAllAux(10, [5,12,31,7,25] ))
The current output is:
[50, [120, [310, [70, [250, 0]]]]]
However, it should be:
[50,120,310,70,250]
I know I am close, but I am at a complete loss at this point. The restrictions of no loops and solely recursion has left me boggled!
Your multAllAux function returns a list. If you append a list to another list, you get this nested list kind of structure that you are getting right now.
If you instead use the "extend" function; it will work as expected.
>>> a = [1, 2, 3]
>>> a.extend([4, 5])
>>> a
[1, 2, 3, 4, 5]
extend takes the elements from a second list and adds them to the first list, instead of adding the second list itself which is what append does!
Your function also returns a zero at the end of the list, which you don't need. You can try this:
def mult(k, A: list) -> list:
return [k * A[0]] + mult(k, A[1:]) if A else []
The problem is here:
B.append(multAllAux(k,A[1:])))
What .append(..) does is it takes the argument, considers it as a single element and adds that element to the end of the list. What you want is to concatenate to the list (ie the item being added should be seen as a list of elements rather than one single element).
You can say something like: B = B + multAllAux(..) or just use +=
B += multAllAux(...)
BTW, if you wanted to multiply a single number to a list, there is a very similar construct: map(..). Note that this behaves slightly differently depending on whether you're using Py2 or Py3.
print(map(lambda x: x * 10, [5,12,31,7,25]))
I am trying to perform in-place modification of a list of list on the level of the primary list. However, when I try to modify the iterating variable (row in the example below), it appears to create a new pointer to it rather than modifying it.
Smallest example of my problem.
c = [1,2,3]
for x in c:
x = x + 3
print(c) #returns [1,2,3], expected [4,5,6]
The above example is a trivial example of my problem. Is there a way to modify x elementwise, in-place and have the changes appear in C?
Less trivial example of my problem. I am switching all 0's to 1's and vice-versa.
A = [[1,1,0],
[1,0,1],
[0,0,0]]
for row in A:
row = list(map(lambda val: 1 - val, row))
print(A)
Expected
A = [[0,0,1],
[0,1,0],
[1,1,1]]
Returned
A = [[1,1,0],
[1,0,1],
[0,0,0]]
update:
Great answers so far. I am interested how the iterating variable (row in the second example) is linked to the iterable variable (A in the second example).
If I do the following, which reverses each sublist of A, it works perfectly.
Why does the following example, where I modify the iterating variable works but the above examples do not?
A = [[1,1,0],
[1,0,1],
[0,0,0]]
for row in A:
row.reverse()
print(A)
#returns, as expected
A = [[0, 1, 1],
[1, 0, 1],
[0, 0, 0]]
I found this in the docs: https://docs.python.org/3/tutorial/controlflow.html#for
Python’s for statement iterates over the items of any sequence (a list
or a string), in the order that they appear in the sequence.
If you need to modify the sequence you are iterating over while inside
the loop (for example to duplicate selected items), it is recommended
that you first make a copy. Iterating over a sequence does not
implicitly make a copy.
I was wrong in my first response, when iterating through a list it returns the actual items in that list. However, it seems they cannot be edited directly while they are being iterated through. This is why iterating through the integers the length of the list works.
As for why the .reverse() function works, I think it's because it is affecting a list instead of a value. I tried to use similar built in functions on nonlist datatypes like .replace() on strings and it had no effect.
All of the other list functions I tried worked: .append(), .remove(), and .reverse() as you showed. I'm not sure why this is, but I hope it clears up what you can do in for loops a bit more.
Answer to old question below:
The way you are using the for loops doesn't affect the actual list, just the temporary variable that is iterating through the list. There are a few ways you can fix this. Instead of iterating through each element you can can count up to the length of the list and modify the list directly.
c = [1,2,3]
for n in range(len(c)):
c[n] += 3
print(c)
You can also use the enumerate() function to iterate through both a counter and list items.
c = [1,2,3]
for n, x in enumerate(c):
c[n] = x + 3
print(c)
In this case, n is a counter and x is the item in the list.
Finally, you can use list comprehension to generate a new list with desired differences in one line.
c = [1, 2, 3]
d = [x + 3 for x in c]
print(d)
The usual way to poke values into an existing list in Python is to use enumerate which lets you iterate over both the indices and the values at once -- then use the indices to manipulate the list:
c = [1,2,3]
for index, value in enumerate(c):
c[index] = value + 3
For your second example you'd do almost the same:
A = [[1,1,0],
[1,0,1],
[0,0,0]]
for row in A:
for index, val in row:
row[index] = 0 if val > 0 else 1
In the second example the list objects in A become the loop variable row -- and since you're only mutating them (not assigning to them) you don't need enumerate and the index
If you want to keep it consice without creating an additional variable, you could also do:
c = [1,2,3]
print(id(c))
c[:] = [i+3 for i in c]
print(c, id(c))
Output:
2881750110600
[4, 5, 6] 2881750110600
Using list comprehension here also will work:
A = [[1,1,0],
[1,0,1],
[0,0,0]]
A = [[0 if x > 0 else 1 for x in row] for row in A]
print(A)
Output:
[[0, 0, 1],
[0, 1, 0],
[1, 1, 1]]
I am trying to solve a seemingly simple problem on Python. I am trying to update the last 3 element of a list to other integers. Here is the code:
list = [0,1,2,3,4]
for i in xrange(len(list[2:])):
list[2:][i] = 44444
print list
But when I print the list, it still remains the same. I observe the changes in debugger and I found that the list doesn't update in the loop. I tried searching elsewhere on Google and Stack Overflow, but none of them provide answers to this simple problem.
Let me know what you guys think about this. Thanks.
A slice of a list is a new list; it doesn’t reference the original or anything like that. Assign to list[2 + i] instead. (You can avoid making an extra slice to get the length in the same way.)
list = [0, 1, 2, 3, 4]
for i in xrange(len(list) - 2):
list[2 + i] = 44444
print list
A slice creates a new list, unless you assign to it:
>>> values = [0, 1, 2, 3, 4]
>>> values[-3:] = [4444] * 3
>>> values
[0, 1, 4444, 4444, 4444]
By using for i in xrange(len(list[2:])): you are reducing the length of list from 5 to 3. Your loop would iterate only for the first 3 list items.
Instead you could do something like this:
a=[0,1,2,3,4,5]
for i in range(3,len(a)):
a[i]=444
print(a)
I've looked into the many posts about getting every nth item of an array, and I used the method for slicing even and odd indices. However, I end up with an empty array for the final object. Any suggestions?
floc1 is an array, and I want to subtract every odd element from every even element:
period = abs(floc1[0::2] - floc1[1::2])
This currently gives me an empty array.
EDIT:
I've tried everything suggested in the comments below. The only thing that generated a different error was:
period = [i-j for i, j in zip(floc1[0::2], floc1[1::2])]
This gives:
Phi12 = ((tau)/(period))
ValueError: operands could not be broadcast together with shapes (1,8208) (0,)
In reference to:
Phi12 = ((tau)/(period))
Again, floc1 is definitely not an empty array. I saved it to a text file to confirm.
Your example gives an error if floc1 is a list (which people often call an "array"). For a list you can do it this way.
>>> floc1 = [11, 5, 6, 2]
>>> it = iter(floc1)
>>> [x - next(it) for x in it]
[6, 4]
You can also use zip if you prefer see #wenzul's answer
If floc1 is a numpy.array - what you have already works
>>> import numpy as np
>>> floc1 = np.array([11, 5, 6, 2])
>>> abs(floc1[0::2] - floc1[1::2])
array([6, 4])
Perhaps your floc1 is actually an empty array
It's not working because you try to substract a list from a list.
You need to do that element-wise.
>>> for i, k in zip(floc1[0::2], floc1[1::2]):
... print abs(i-k)
Also look into this.