Translate Matlab's vector assignment into Python form

Question:

I’m trying to translate some Matlab code into Python (using NumPy). I’m not very familiar with Matlab, and I’ve encountered a line that I’m having trouble parsing:

w(idx(1:p, 1), 1) = v(idx(1:p, 1), 1) - theta;

I’d hazard a guess that a p-long head of x is being used as indices to select p entries of w, and that those entries in w are being replaced by corresponding entries in v (less a scalar theta).

Messing around in Octave, that seems like an accurate description of what it’s doing, but I can’t find any documentation to that effect.

In any case, what’s the best way to re-write this code in Python? I’ve looked at the NumPy ‘Tentative Tutorial’ to try and find an elegant way to do it, and it looks like this might be what I’m looking for. However, I’m having trouble making it look nice, particularly with the assignment operator. Are there any more elegant or Python-idiomatic ways to do this assignment operation?

Asked By: eapi

||

Answers:

This is basically what @Dan wrote in the comments, but accounts for zero-based indexing in python:

w[idx[:p, 0], 0] = v[idx[:p, 0], 0] - theta

Not sure if you wanted something more elegant than that. Those zeros are required if only the first column should be modified.

Answered By: askewchan

You’re right about the basic behavior. A p-length sub-vector from the first column of an indexing matrix idx is being used to select elements from v and place them into the same locations in the matrix w after first adjusting their values by the scalar theta.

It is critical to use one-based indexing for MATLAB and zero-based indexing for numpy.

In MATLAB,

clear

% Data matrices
w = zeros(5,5)
v = diag([10,20,30,40,50]) * ones(5,5)

% Indexing matrix
idx = ceil(5*rand(5, 5))

% Selection and adjustment parameters
p = 3    
theta = 1

% Apply adjustment and selection
w(idx(1:p, 1), 1) = v(idx(1:p, 1), 1) - theta

produces the output

w =

     0     0     0     0     0
     0     0     0     0     0
     0     0     0     0     0
     0     0     0     0     0
     0     0     0     0     0


v =

    10    10    10    10    10
    20    20    20    20    20
    30    30    30    30    30
    40    40    40    40    40
    50    50    50    50    50


idx =

     3     1     2     3     4
     1     1     2     1     3
     4     1     2     2     2
     1     1     5     1     1
     1     2     4     5     4


theta =

     1


p =

     3


w =

     9     0     0     0     0
     0     0     0     0     0
    29     0     0     0     0
    39     0     0     0     0
     0     0     0     0     0

And, the equivalent Python code using numpy

import numpy as np

# Data arrays
w = np.zeros((5,5))
v = np.dot(np.diag([10, 20, 30, 40, 50]), np.ones((5,5)))
print "w = "
print w
print "v = "
print v

# Indexing array
idx = np.floor(5 * np.random.rand(5,5)).astype(int)
print "idx = "
print idx

# Selection and adjustment parameters
theta = 1
p = 3

# Apply selection and adjustment
w[idx[:p, 0], 0] = v[idx[:p, 0], 0] - theta
print "w = "
print w

which produces the output

w = 
[[ 0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.]
 [ 0.  0.  0.  0.  0.]]
v = 
[[ 10.  10.  10.  10.  10.]
 [ 20.  20.  20.  20.  20.]
 [ 30.  30.  30.  30.  30.]
 [ 40.  40.  40.  40.  40.]
 [ 50.  50.  50.  50.  50.]]
idx = 
[[0 2 2 0 3]
 [1 2 1 2 4]
 [2 2 4 3 4]
 [0 1 1 4 4]
 [0 1 0 4 3]]
w = 
[[  9.   0.   0.   0.   0.]
 [ 19.   0.   0.   0.   0.]
 [ 29.   0.   0.   0.   0.]
 [  0.   0.   0.   0.   0.]
 [  0.   0.   0.   0.   0.]]
Answered By: Jed