Write a 2-d array in a for-loop - python

I want to create 2 arrays from the following for-loop:
with open('y.txt', 'w') as f:
for j in range (1, 3):
xN = 0.5 + 0.5*random.uniform(0, 1)
r = 3.8 + 0.15*random.uniform(0, 1)
for i in range (1, 313+1):
xNew = logistic_map(xN, r)
xN = xNew
f.write("%f" % xNew)
This is of course creating a text file of 313*2=626 rows.
What I want to do is to be able to automatically create j arrays:
Q(j = 1) = the first 313 points
Q(...)
Q(j = N) = the last 313 points.
Also, how do I save this to a text file, with 313 rows and j columns? The text file I have now just saves a file with 626 rows.

To create a 2D array, you can modify your code like so:
import numpy as np
Q = []
for j in range (1, 3):
xN = 0.5 + 0.5*random.uniform(0, 1)
r = 3.8 + 0.15*random.uniform(0, 1)
temp = []
for i in range (1, 313+1):
xNew = logistic_map(xN, r)
xN = xNew
temp.append(xNew)
Q.append(xNew) # Saves each row of 313 points as a separate sub-array
Q = np.transpose(np.array(Q)) # Convert this to an array and take the transpose of it
Then you can use np.savetxt to save this as a text file.
However, if you don't actually need the sub-arrays to contain 313 points, you can add the points in the transpose order directly, thereby skipping the later np.transpose() step. Like this:
import numpy as np
Q = [[0 for j in range(2)] for i in range (313)] # Creates an array of zeros with 2 columns and 313 rows
for j in range (1, 3):
xN = 0.5 + 0.5*random.uniform(0, 1)
r = 3.8 + 0.15*random.uniform(0, 1)
for i in range (1, 313+1):
xNew = logistic_map(xN, r)
xN = xNew
Q[i][j] = xNew
Q = np.array(Q) # Convert this to an array and take the transpose of it

Related

Generating a random line on a 2d array in python

I've got a 2d array of zeros: 250 by 250. And I want to generate a random straight random line of a specific length (haven't yet decided). Obviously, since it's a line the values that turn from zero to one must be connected in some way, vertically, horizontally, or diagonally; and it also has to be straight. How could I do this? I'm quite stuck with this problem, any help would be appreciated.
We can do:
import numpy as np
SIZE = 250
arr = np.zeros((SIZE, SIZE))
M_POS = np.arange(-SIZE, SIZE)
M_POS = np.r_[M_POS, 1 / M_POS[M_POS!=0]]
M = np.random.choice(M_POS, 1)[0]
N = np.random.choice(np.arange(-SIZE, SIZE), 1)[0]
L = 50
P0 = np.array([0, N])
X_Y = np.array([1, 1 / M]) if abs(M) < 1 else np.array([1, M])
draw_in = np.add(np.repeat([P0], L, axis=0),
np.repeat([X_Y], L, axis=0) * np.arange(L)[:, np.newaxis]).astype(int)
draw_in = draw_in[((draw_in < SIZE) & (draw_in>0)).all(axis=1)]
arr[draw_in[:, 0], draw_in[:, 1]] = 1

How to convert an array of frames into array of frame pairs?

I have a numpy array of arrays, say 400x80. I want to turn it into an array 400x160 so that each item would be formed like this:
Here each frame of 80 is copied into the beginning of the next frame and the first frame gest 80 zeroes. So how to do such thing in numpy? Is there a mechanism that can generalize to three or more frames?
Lets assume that your data is in X, then
np.hstack((np.vstack((np.zeros(X.shape[1]), X[:-1])), X))
where:
np.vstack((np.zeros(X.shape[1]), X[:-1]))
creates the first column, we add a row of zeros, and cut the last row
and then with hstack we just combine the two "columns" together.
import numpy as np
X = np.random.normal(size=(400, 80))
print(np.hstack((np.vstack((np.zeros(X.shape[1]), X[:-1])), X)).shape)
gives (400, 160) as expected.
Or you can do things manually:
Y = []
previos = np.zeros(X.shape[1])
for row in X:
Y.append(np.vstack((previous, row)))
previous = row
Y = np.array(Y)
You are trying to create a sliding window. If you want a view that looks into the original buffer, indexing the same memory locations multiple times, you can make some adjustments.
m, n = a.shape
p = 2 * n
x = np.lib.stride_tricks.as_strided(a, shape=(m * ((n - 1) + p) // p, p), strides=a.strides)
This is the totally general approach. If you're guaranteed p % n == 0, then for k = p // n, you can do
x = np.lib.stride_tricks.as_strided(a, shape=(m - k + 1, n * k), strides=a.strides)
In either case, to avoid memory issues, you can use x.copy()

More pythonic way of creating within-class scatter matrix

I am looking for a better way of calculating the following
import numpy as np
np.random.seed(123)
# test code
t = np.random.randint(3, size = 100)
X = np.random.random((100, 3))
m = np.random.random((3, 3))
# current method
res = 0
for k in np.unique(t):
for row in X[t == k] - m[k]:
res += np.outer(row, row)
res
"""
Output:
array([[12.45661335, -3.51124346, 3.75900294],
[-3.51124346, 14.85327689, -3.02281263],
[ 3.75900294, -3.02281263, 18.30868772]])
"""
I would prefer getting rid of the for loops using numpy.
This is the within-class scatter matrix for fischers linear discriminant.
You can write as follows:
Y = X - m[t]
np.matmul(Y.T, Y)
This is because sum_i x_i x'_i = X' X, where X is (N, 3) matrix and x_i = X[i,:], i.e. i-th row of X. ' indicates the transpose.

Add Condition on generated numpy

I have piece of code :
V = numpy.floor(3*np.random.rand(5,5))
print V
It create random result of array in 5x5 table, how to add condition "1" only generate x times, "2" only generate y times, else are "0".
Thanks
Try this:
import numpy as np
def newArray( x, y, n):
if x + y > n ** 2:
print "Values error!"
return
res = [[0 for col in range(n)] for row in range(n)]
# Create roulette
roulette = range(0, n ** 2)
printkxtimes(res, roulette, 1, x, n)
printkxtimes(res, roulette, 2, y, n)
print res
# This function draws random element from roulette,
# gets the position in array and sets value of this position to k.
# Then removes this element from roulette to prevent drawing it again
def printkxtimes(array, roulette, k, x, n):
for i in xrange(0, x):
r = int(np.floor(roulette.__len__()*np.random.rand(1))[0])
array[roulette[r] / n][roulette[r] % n] = k
roulette.pop(r)
newArray(10,2,5)
A little explanation of roulette :
Every element of table res can be represented equivalently with a number from range(0, n^2) :
z = row*n + column <=> row = int(z/n) , column= z%n
We can then represent the list of positions in table res as the table [0,1,...,n^2-1]
How about the following?
import numpy as np
shape = (5, 5)
area = shape[0] * shape[1]
np.random.permutation([1]*x + [2]*y + [0]*(area-x-y)).reshape(shape)
Seems pretty simple. You take a random permutation of [1, ... 1, 2, ... 2, 0, ... 0] and then you just turn it into a square. I'm not too sure but it also seems less computationally expensive and is also extensible to n numbers or dimensions quite easily.

Can I vectorize this 2d array indexing where the 2nd dimension depends on the value of the first?

In the example below I have a 2D array that has some real results that are shifted and padded. The shifts depend on the row (the padding is used to make the array rectangular as required by numpy). Is it possible to extract the real results without a Python loop?
import numpy as np
# results are 'shifted' where the shift depends on the row
shifts = np.array([0, 8, 4, 2], dtype=int)
max_shift = shifts.max()
n = len(shifts)
t = 10 # length of the real results we care about
a = np.empty((n, t + max_shift), dtype=int)
b = np.empty((n, t), dtype=int)
for i in range(n):
a[i] = np.concatenate([[0] * shifts[i], # shift
(i+1) * np.arange(1, t+1), # real data
[0] * (max_shift - shifts[i]) # padding
])
print "shifted and padded\n", a
# I'd like to remove this Python loop if possible
for i in range(n):
b[i] = a[i, shifts[i]:shifts[i] + t]
print "real data\n", b
You can use two array to get the data out:
a[np.arange(4)[:, None], shifts[:, None] + np.arange(10)]
or:
i, j = np.ogrid[:4, :10]
a[i, shifts[:, None]+j]
This is called Advanced indexing in NumPy document.

Categories