More "modern python" way of doing things.
[[ randint(0,4) for x in range(0,4)] for y in range(0,4)]
Its simply a pair of nested list comprehensions.
Answer from Shayne on Stack OverflowMore "modern python" way of doing things.
[[ randint(0,4) for x in range(0,4)] for y in range(0,4)]
Its simply a pair of nested list comprehensions.
The only time when you add 'rows' to the status array is before the outer for loop.
So - status[0] exists but status[1] does not.
you need to move status.append([]) to be inside the outer for loop and then it will create a new 'row' before you try to populate it.
python - Filling a 2D Array with Another Array - Stack Overflow
python - How to populate a 2d array? - Stack Overflow
How to fill each element of a 2d array with a for loop in python - Stack Overflow
fill 2d array python value from a list / 1d array - Stack Overflow
Are you necessarily looking to use for-loops? I am asking because this problem can be solved in simpler and more efficient ways such as:
import numpy as np
a_values = np.random.rand(20,402) #Store random values in a_values with a shape of 20 rows and 402 columns
avg_columns = a_values.mean(axis=0) #Calculate the mean of each column
print(avg_columns)
Documentation for generating random values: numpy.random.rand
EDIT:
I assumed that xa is randomized in each iteration (make sure to replace it with the xa that you are generating). You can initialize an empty a_values array, and add the generated xa array to it in each iteration using np.vstack. For the first iteration, when a_value is empty, I made it equal to xa (if a_values.size else xa).
import numpy as np
a_values = np.array([])
for i in range(20):
xa = np.random.rand(1,402)
a_values = np.vstack([a_values, xa]) if a_values.size else xa
avg_columns = a_values.mean(axis=0) #Average of each column
Documentation for vstack: numpy.vstack
I don't think you can change the shape of A_values after it's defined. So you should start with:
A_values = numpy.zeros([20,402])
And if your for loop is iterating through the rows, your index should be [i, 1] (numpy array indexes are not like cartesian plane coords).
But you want to change entire rows of A_values, to do this you use just the first index:
A_values[row] = some_row
Remember that "some_row" needs to have the proper lenght, otherwise you get a ValueError.
Your final code will look like this:
A_values = numpy.zeros([20, 402])
for i in range(0,20):
A_values([i]) = xa
PS: You should describe the errors you are getting and be clearer if you want help with the "xa" values as well...
There are fancier ways, but this is the most straightforward:
>>> rows = 3
>>> columns = 7
>>> n = 1
>>> matrix = []
>>> for _ in range(rows):
... sub = []
... for _ in range(columns):
... sub.append(n)
... n += 1
... matrix.append(sub)
...
>>> matrix
[[1, 2, 3, 4, 5, 6, 7], [8, 9, 10, 11, 12, 13, 14], [15, 16, 17, 18, 19, 20, 21]]
And for good measure, a fancy way:
>>> import itertools
>>> counter = itertools.count(1)
>>> rows = 3
>>> columns = 7
>>> matrix = [[n for n, _ in zip(counter, range(columns))] for _ in range(rows)]
>>> matrix
[[1, 2, 3, 4, 5, 6, 7], [9, 10, 11, 12, 13, 14, 15], [17, 18, 19, 20, 21, 22, 23]]
>>>
Use list comprehension. You want 3 rows so the base of the list comprehension is: [for y in range(rows)]. You want to have incrementing numbers starting with a number divisible by columns but starting from 1 so: range(columns*y+1,...) and you want to have columns range (7) so range(columns*y+1,columns+(columns*y+1)) and then turn that into a list.
rows=3
columns=7
matrix=[list(range(columns*y+1,columns+(columns*y+1))) for y in range(rows)]
print(matrix)
#outputs: [[1, 2, 3, 4, 5, 6, 7], [8, 9, 10, 11, 12, 13, 14], [15, 16, 17, 18, 19, 20, 21]]
The problem here is in line
board[x:y] = player;
the [x:y] notation is for assigning ranges while what you really need is probably
board[x][y] = player
Normally you would get an error because assigning single value to a range will throw TypeError. In this case you are assigning string which python treats as a list of characters let's say.
board[x:y] is slicing syntax. In your case, you seem to have tried board[1:1] = "x". Let's see what that does:
board[1:1] refers to the part of the list from index 1 to index 1 (an empty part, but a part nonetheless):
['','',''], ['','',''], ['','','']
0 1 2 3
โ
Since you set that slice to "x" (and a string is a sequence), the list now becomes:
['','',''], 'x', ['','',''], ['','','']
0 1 2 3 4
What you want to do instead is access the second list inside the list (board[1]), and the 1st element of that inner list (board[1][1]):
board[x:y] = player
I know that you can create shared numpy arrays that can be changed from different threads (assuming that the changed areas don't overlap). Here is the sketch of the code that you can use to do that (I saw the original idea somewhere on stackoverflow, edit: here it is https://stackoverflow.com/a/5550156/1269140 )
import multiprocessing as mp ,numpy as np, ctypes
def shared_zeros(n1, n2):
# create a 2D numpy array which can be then changed in different threads
shared_array_base = mp.Array(ctypes.c_double, n1 * n2)
shared_array = np.ctypeslib.as_array(shared_array_base.get_obj())
shared_array = shared_array.reshape(n1, n2)
return shared_array
class singleton:
arr = None
def dosomething(i):
# do something with singleton.arr
singleton.arr[i,:] = i
return i
def main():
singleton.arr=shared_zeros(1000,1000)
pool = mp.Pool(16)
pool.map(dosomething, range(1000))
if __name__=='__main__':
main()
You can create an empty numpy.memmap array with the desired shape, and then use multiprocessing.Pool to populate its values. Doing it correctly would also keep memory footprint of each process in your pool relatively small.
I guess the easiest way to do this is to reshape an arange from 0 to 100:
>>> np.arange(100).reshape(10, -1)
array([[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19],
[20, 21, 22, 23, 24, 25, 26, 27, 28, 29],
[30, 31, 32, 33, 34, 35, 36, 37, 38, 39],
[40, 41, 42, 43, 44, 45, 46, 47, 48, 49],
[50, 51, 52, 53, 54, 55, 56, 57, 58, 59],
[60, 61, 62, 63, 64, 65, 66, 67, 68, 69],
[70, 71, 72, 73, 74, 75, 76, 77, 78, 79],
[80, 81, 82, 83, 84, 85, 86, 87, 88, 89],
[90, 91, 92, 93, 94, 95, 96, 97, 98, 99]])
Here the .reshape(..) call will thus transform the matrix such that it is a 2D-array, with 10 "rows" and a number of columns such that the total amount of cells is 100.
In case you do not want to construct a 2D-array, but a Python list of 1D arrays, we can use list comprehension:
[np.arange(i, i+10) for i in range(0, 100, 10)]
A more pythonic way of doing your task would be one liner
import numpy as np
print(np.reshape(np.arange(0,100),(10,10)))
As I explained in my answer to your previous question, you really need to vectorize arbitrary_function.
You can do this by just calling np.vectorize on the function, something like this:
Z = np.vectorize(arbitrary_function)(np.arange(3), np.arange(5).reshape(5, 1))
But that will only give you a small speedup. In your case, since arbitrary_function is doing a huge amount of work (including opening and parsing an Excel spreadsheet), it's unlikely to make enough difference to even notice, much less to solve your performance problem.
The whole point of using NumPy for speedups is to find the slow part of the code that operates on one value at a time, and replace it with something that operates on the whole array (or at least a whole row or column) at once. You can't do that by looking at the very outside loop, you need to look at the very inside loop. In other words, at arbitrary_function.
In your case, what you probably want to do is read the Excel spreadsheet into a global array, structured in such a way that each step in your process can be written as an array-wide operation on that array. Whether that means multiplying by a slice of the array, indexing the array using your input values as indices, or something completely different, it has to be something NumPy can do for you in C, or NumPy isn't going to help you.
If you can't figure out how to do that, you may want to consider not using NumPy, and instead compiling your inner loop with Cython, or running your code under PyPy. You'll still almost certainly need to move the "open and parse a whole Excel spreadsheet" outside of the inner loop, but at least you won't have to figure out how to rethink your problem in terms of vectorized operations, so it may be easier for you.
rows = 10
cols = 10
Z = numpy.array([ arbitrary_function(each_point, each_axes) for each_axes in range(cols) for each_point in range(rows) ]).reshape((rows,cols))
maybe?
First you have to install numpy using
$ pip install numpy
Then the following should work
import numpy as np
n = 100
matrix = np.zeros((n,2)) # Pre-allocate matrix
for i in range(1,n):
matrix[i,:] = [3*i, i**2]
A faster alternative:
col1 = np.arange(3,3*n,3)
col2 = np.arange(1,n)
matrix = np.hstack((col1.reshape(n-1,1), col2.reshape(n-1,1)))
Even faster, as Divakar suggested
I = np.arange(n)
matrix = np.column_stack((3*I, I**2))
This is very pythonic form to produce a list, which you can easily swap e.g. for np.array, set, generator etc.
n = 10
[[i*3, i**2] for i, i in zip(range(0,n), range(0,n))]
If you want to add another column it's no problem. Simply
[[i*3, i**2, i**(0.5)] for i, i in zip(range(0,n), range(0,n))]
The four sums you want can be calculated efficiently like this:
import numpy as np
arr = np.array(data)
w = arr[0::2,0] # array([ 1, 3, 5, 13])
x = arr[0::2,1] # array([ 7, 9, 11, 14])
y = arr[1::2,0] # array([ 2, 4, 6, 15])
z = arr[1::2,1] # array([ 8, 10, 12, 16])
B = [[w.sum(), x.sum()], [y.sum(), z.sum()]]
arr[1::2,0] means "Starting from row 1, take every second row, then take column 0."
def slice_array(raw_data):
ret = [[0,0],
[0,0]]
for d in range(len(raw_data)):
if d % 2 == 0:
ret [0][0] += raw_data[d][0]
ret [0][1] += raw_data[d][1]
if d % 2 == 1:
ret [1][0] += raw_data[d][0]
ret [1][1] += raw_data[d][1]
return ret
This should work. Just give the array you want to slice as input.