NumPy slicing squares in 2D array - python

I want to create a heightfield map that consists of squares of random height. Given an array of NxN, I want that every square of size MxM, where M<N, will be at the same random height, with the height sampled from a uniform distribution. For example, if we have N = 6 and M = 2, we would have:
0.2, 0.2, 0.6, 0.6, 0.1, 0.1,
0.2, 0.2, 0.6, 0.6, 0.1, 0.1,
0.5, 0.5, 0.3, 0.3, 0.8, 0.8,
0.5, 0.5, 0.3, 0.3, 0.8, 0.8,
0.6, 0.6, 0.4, 0.4, 0.9, 0.9,
0.6, 0.6, 0.4, 0.4, 0.9, 0.9
For now, I've come up with an inefficient way of doing it with 2 nested for loops. I'm sure there must be an efficient and elegant way to do that with NumPy slicing.

This solution using the repeat() method should work for N/M integer.
import numpy as np
N = 6
M = 2
values = np.random.random( [N//M, N//M] )
y = values.repeat( M, axis=0 ).repeat( M, axis=1 )
print(y)

Related

Break DataFrame into multiple DataFrames depending on monotonically decreasing nature

Assume, I have a data frame series containing increasing set of values and decreasing set of values. (Like a sawtooth pattern).
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
y = list(np.linspace(0, 1, 3)) + list(np.linspace(1,0, 11)) * 5
x = list(range(len(y)))
df = pd.DataFrame({"x": x, "y":y})
df.plot("x", "y")
Now I would like to extract these down-sliding sections in to separate dfs. What would be the best way to do this ?
What I am expecting to see a list of dfs as below (image shows the data of the first df)
pd.DataFrame({"x": range(11), "y":list(np.linspace(1,0, 11))}).plot("x", "y")
Use:
s = (df['y']-df['y'].shift(-1)>0)
t = s-s.shift(1)
u = t[t>=0].astype(int).cumsum()
u = u[u>0]
df.loc[u.index].groupby(u)['y'].apply(list)
Output"
y
1 [1.0, 0.9, 0.8, 0.7, 0.6, 0.5, 0.3999999999999...
2 [1.0, 0.9, 0.8, 0.7, 0.6, 0.5, 0.3999999999999...
3 [1.0, 0.9, 0.8, 0.7, 0.6, 0.5, 0.3999999999999...
4 [1.0, 0.9, 0.8, 0.7, 0.6, 0.5, 0.3999999999999...
5 [1.0, 0.9, 0.8, 0.7, 0.6, 0.5, 0.3999999999999...
Name: y, dtype: object

Selecting items on a matrix based on indexes given by an array

Consider this matrix:
[0.9, 0.45, 0.4, 0.35],
[0.4, 0.8, 0.3, 0.25],
[0.5, 0.45, 0.9, 0.35],
[0.2, 0.18, 0.8, 0.1],
[0.6, 0.45, 0.4, 0.9]
and this list:
[0,1,2,3,3]
I want to create a list that looks like the following:
[0.9, 0.8, 0.9, 0.1, 0.9]
To clarify, for each row, I want the element of the matrix whose column index is contained in the first array. How can I accomplish this?
Zip the two lists together as below
a=[[0.9, 0.45, 0.4, 0.35],[0.4, 0.8, 0.3, 0.25],[0.5, 0.45, 0.9, 0.35],[0.2, 0.18, 0.8, 0.1],[0.6, 0.45, 0.4, 0.9]]
b=[0,1,2,3,3]
[i[j] for i,j in zip(a,b)]
Result
[0.9, 0.8, 0.9, 0.1, 0.9]
This basically pairs up each sublist in the matrix with the element of your second list in order with zip(a,b)
Then for each pair you choose the bth element of a
If this is a numpy array, you can pass in two numpy arrays to access the desired indices:
import numpy as np
data = np.array([[0.9, 0.45, 0.4, 0.35],
[0.4, 0.8, 0.3, 0.25],
[0.5, 0.45, 0.9, 0.35],
[0.2, 0.18, 0.8, 0.1],
[0.6, 0.45, 0.4, 0.9]])
indices = np.array([0,1,2,3,3])
data[np.arange(data.shape[0]), indices]
This outputs:
[0.9 0.8 0.9 0.1 0.9]
In the first array [0, 1, 2, 3, 3], the row is determined by the index of the each element, and the value at that index is the column. This is a good case for enumerate:
matrix = [[ ... ], [ ... ], ...] # your matrix
selections = [0, 1, 2, 3, 3]
result = [matrix[i][j] for i, j in enumerate(selections)]
This will be much more efficient than looping through the entire matrix.
Loop through both arrays together using the zip function.
def create_array_from_matrix(matrix, indices):
if len(matrix) != len(indices):
return None
res = []
for row, index in zip(matrix, indices):
res.append(row[index])
return res

Open interval (a,b) and half-open interval (a,b] using Python's linspace

A half-open interval of the form [0,0.5) can be created using the following code:
rv = np.linspace(0., 0.5, nr, endpoint=False)
where nr is the number of points in the interval.
Question: How do I use linspace to create an open interval of the form (a,b) or a half-open interval of the form (a,b]?
Probably the simplest way (since this functionality isn't built in to np.linspace()) is to just slice what you want.
Let's say you're interested in the interval [0,1] with a spacing of 0.1.
>>> import numpy as np
>>> np.linspace(0, 1, 11) # [0,1]
array([0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1. ])
>>> np.linspace(0, 1, 11-1, endpoint=False) # [0,1)
array([0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9])
>>> np.linspace(0, 1, 11)[:-1] # [0,1) again
array([0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9])
>>> np.linspace(0, 1, 11)[1:] # (0,1]
array([0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1. ])
>>> np.linspace(0, 1, 11)[1:-1] # (0,1)
array([0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9])

Numpy Arange generating values of inconsistent decimal points

Can someone explain me what's happening here?
Why is there more decimal points for 0.3 and 0.7 values.
I just want 1 decimal point values.
threshold_range = np.arange(0.1,1,0.1)
threshold_range.tolist()
[Output]: [0.1, 0.2, 0.30000000000000004, 0.4, 0.5, 0.6, 0.7000000000000001, 0.8, 0.9]
Use np.round
Ex.
import numpy as np
threshold_range = np.arange(0.1,1,0.1)
print(threshold_range.tolist())
print(np.round(threshold_range, 2).tolist())
O/P:
[0.1, 0.2, 0.30000000000000004, 0.4, 0.5, 0.6, 0.7000000000000001, 0.8, 0.9]
[0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9]
Solution: You can simply use round function:
threshold_range = np.arange(0.1,1,0.1).round(1)
threshold_range.tolist() # [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9]
Reason of error: I think it has to do with floating point precision ;)

Two denominational array slicing

I have a portion of Viterbi algorithm that I want to manipulate. I need to understand the slicing part in this code:
import numpy as np
A = np.array([[0.6, 0.2, 0.2], [0.5, 0.3, 0.2], [0.4, 0.1, 0.5]])
pi = np.array([0.5, 0.2, 0.3])
O = np.array([[0.7, 0.1, 0.2], [0.1, 0.6, 0.3], [0.3, 0.3, 0.4]])
states = UP, DOWN, UNCHANGED = 0, 1, 2
observations = [UP, UP, DOWN]
alpha = np.zeros((len(observations), len(states))) # time steps x states
alpha[:,:] = float('-inf')
backpointers = np.zeros((len(observations), len(states)), 'int')
***alpha[0, :] = pi * O[:,UP]***
in the last line print out the O[:,UP] what is should give me:
[0.7, 0.1, 0.2] I believe
instead, it gives me:
O[:,UP]
Out[15]: array([ 0.7, 0.1, 0.3])
I tried to look into this Understanding Python's slice notation
I couldn't understand why it changes the last element of the array.
Also, I run this:
O[:,UNCHANGED]
Out[17]: array([ 0.2, 0.3, 0.4])
I'm still newbie in python, I need some help
You are mixing up the notation for columns and rows.
You print O[:,UP] which gives you all the rows and just the "UP"th column (index 0).
Your O is:
array([[ 0.7, 0.1, 0.2],
[ 0.1, 0.6, 0.3],
[ 0.3, 0.3, 0.4]])
And O[:,0] is
#↓ this column
array([[ 0.7, 0.1, 0.2],
[ 0.1, 0.6, 0.3],
[ 0.3, 0.3, 0.4]])
where O[0,:] would be
array([[ 0.7, 0.1, 0.2], #This row
[ 0.1, 0.6, 0.3],
[ 0.3, 0.3, 0.4]])
And just to make the last part clear, O[:,UNCHANGED] is O[:,2] which is here:
#↓ this column
array([[ 0.7, 0.1, 0.2],
[ 0.1, 0.6, 0.3],
[ 0.3, 0.3, 0.4]])

Categories

Resources