I have the following:
- A set of
K
time-series in a numpy array with dimensionsT x K
. - A set of
P
permuted approximation of them in a numpy array with dimensionsP times T
.
I need a dictionary that tells me which is the most probable permutation. For that I've created the following function, but I would like to know if can be done in a more efficient way and with less code to do this.
def find_permutation(true, permuted):
"""
Finds the most probable permutation of true time series in between permuted time series
:param true: true ordered time series of shape T times X
:param permuted: Permuted time series of shape P times T. P > K
:return: A dict containing {true idx: permuted idx}
"""
N = true.shape[1]
max_comps = permuted.shape[0]
permutation_dict = {}
used_comps = []
corr_matrix = np.zeros((N, max_comps))
# Find correlations
for i in range(N):
for j in range(max_comps):
corr_matrix[i, j] = np.corrcoef(true[:, i], permuted[j, :])[0, 1]
# Find best order
per_matrix = np.argsort(-np.abs(corr_matrix), axis=1)
for i in range(N):
for j in per_matrix[i, :]:
if j in used_comps:
continue
else:
permutation_dict[i] = j
used_comps.append(j)
break
return permutation_dict
if __name__ == "__main__":
import numpy as np
a = np.array([1, 2, 3, 4.])
b = np.array([4, 8, 9, 12.])
c = np.array([9, 5, 8, 9.])
true = np.vstack([a, b, c]).transpose()
permuted = np.vstack([b*0.2, c*0.5, a*0.7])
print(find_permutation(true, permuted))
# {0: 2, 1: 0, 2: 1}
Here a Cython version
# C imports first
cimport numpy as np
# other imports
import numpy as np
import cython
# Type declarations
DTYPE = np.float
ctypedef np.float_t DTYPE_t
@cython.boundscheck(False) # Deactivate bounds checking
@cython.wraparound(False) # Deactivate negative indexing.
def find_permutation(np.ndarray[DTYPE_t, ndim=2] true, np.ndarray[DTYPE_t, ndim=2] permuted):
"""
Finds the most probable permutation of true time series in between permuted time series
:param true: true ordered time series of shape T times X
:param permuted: Permuted time series of shape P times T. P > K
:return: A dict containing {true idx: permuted idx}
"""
cdef unsigned int N = true.shape[1]
cdef unsigned int max_comps = permuted.shape[0]
cdef dict permutation_dict = {}
cdef list used_comps = []
cdef np.ndarray[DTYPE_t, ndim=2] corr_matrix
corr_matrix = np.zeros((N, max_comps))
cdef Py_ssize_t i
cdef Py_ssize_t j
# Find correlations
for i in range(N):
for j in range(max_comps):
corr_matrix[i, j] = np.corrcoef(true[:, i], permuted[j, :])[0, 1]
# Find best order
cdef np.ndarray[long, ndim=2] per_matrix
per_matrix = np.argsort(-np.abs(corr_matrix), axis=1)
for i in range(N):
for j in per_matrix[i, :]:
if j in used_comps:
continue
else:
permutation_dict[i] = j
used_comps.append(j)
break
return permutation_dict
Any suggestion is more than welcome.
P >K
, but in your exampleP == K
and is every time series represented at least once? or better, is there a 1 in each row ofcorr_matrix
\$\endgroup\$P
times series those that are more correlated withK
. That is way onlyK
are returned. In the ideal case, would be at least one 1 for each row, but can happen that two series inpermuted
are more similar to only one intrue
, that's prevented by tracking them usingused_comps
. \$\endgroup\$