This is an issue in rENA 0.3.1, not in ena-python. It is tracked here because it came out of porting rENA to Python. Reported as an observation, not an accusation — it may be fixed upstream or intended, in which case please correct me. Full write-up: docs/rena-upstream-issues.md
Summary
ena.correlations's documented dims parameter only works for a contiguous range starting at 1. Any other subset raises subscript out of bounds, even when every requested dimension exists.
Severity: low — the parameter works for its default-shaped values, so this only bites when selecting other dimensions.
Reproduce
Tested with rENA 0.3.1, R 4.4.2.
library(rENA)
rows <- data.frame(
unit = rep(paste0("U", 1:6), each = 4),
conv = rep(rep(c("c1", "c2"), each = 2), times = 6),
grp = rep(c("g1", "g2"), each = 12),
score = rep(c(10, 20, 30, 40, 50, 60), each = 4),
A = c(1,0,1,0, 0,1,1,1, 1,1,0,1, 0,0,1,0, 1,0,0,1, 0,1,1,0),
B = c(0,1,1,1, 1,1,0,0, 0,1,1,0, 1,0,0,1, 0,1,1,0, 1,0,0,1),
C = c(1,1,0,0, 1,0,1,0, 1,0,0,1, 0,1,1,1, 1,1,0,0, 0,0,1,1),
D = c(0,0,1,1, 0,1,0,1, 0,1,1,0, 1,1,0,0, 0,0,1,1, 1,1,0,0),
stringsAsFactors = FALSE)
acc <- ena.accumulate.data(
units = rows[, "unit", drop = FALSE], conversation = rows[, "conv", drop = FALSE],
metadata = rows[, c("grp", "score")], codes = rows[, c("A","B","C","D")],
window.size.back = 2)
set <- ena.make.set(acc, dimensions = 2)
colnames(as.matrix(set$points))
#> [1] "SVD1" "SVD2" "SVD3" "SVD4" "SVD5" "SVD6" <- all six exist
ena.correlations(set, dims = c(1, 2)) #> OK
ena.correlations(set, dims = c(1, 2, 3)) #> OK
ena.correlations(set, dims = c(1)) #> OK
ena.correlations(set, dims = c(2, 3)) #> Error in optDiff[, dim] : subscript out of bounds
ena.correlations(set, dims = c(1, 3)) #> Error in optDiff[, dim] : subscript out of bounds
ena.correlations(set, dims = c(3, 4)) #> Error in optDiff[, dim] : subscript out of bounds
Root cause
ena.correlations.R uses dims in two different coordinate systems. First to slice, producing a matrix whose columns are numbered 1..length(dims):
svdDiff = matrix(points[point1, dims] - points[point2, dims], ncol=length(dims), nrow=length(point1))
optDiff = matrix(centroids[point1, dims] - centroids[point2, dims], ncol=length(dims), nrow=length(point1))
then to index that matrix, still with the original values:
lapply(dims, function(dim) {
cor(as.numeric(svdDiff[,dim]), as.numeric(optDiff[,dim]), method=method)
});
With dims = c(2, 3), svdDiff has two columns but column 3 is requested. It works for 1:n only because the sliced positions happen to coincide with the requested indices.
Suggested fix
Index by position after slicing:
lapply(seq_along(dims), function(i) {
cor(as.numeric(svdDiff[,i]), as.numeric(optDiff[,i]), method=method)
});
What ena-python does
Takes dimension names (dims=["SVD1", "SVD3"]) and enumerates positionally, so any subset works. A different constraint applies there: ena-python slices points to the model's dimensions, so correlating SVD3 needs make_set(..., dimensions=3) — rENA keeps every dimension in points and never needs this.
Summary
ena.correlations's documenteddimsparameter only works for a contiguous range starting at 1. Any other subset raisessubscript out of bounds, even when every requested dimension exists.Severity: low — the parameter works for its default-shaped values, so this only bites when selecting other dimensions.
Reproduce
Tested with rENA 0.3.1, R 4.4.2.
Root cause
ena.correlations.Rusesdimsin two different coordinate systems. First to slice, producing a matrix whose columns are numbered1..length(dims):then to index that matrix, still with the original values:
With
dims = c(2, 3),svdDiffhas two columns but column 3 is requested. It works for1:nonly because the sliced positions happen to coincide with the requested indices.Suggested fix
Index by position after slicing:
What ena-python does
Takes dimension names (
dims=["SVD1", "SVD3"]) and enumerates positionally, so any subset works. A different constraint applies there: ena-python slicespointsto the model'sdimensions, so correlatingSVD3needsmake_set(..., dimensions=3)— rENA keeps every dimension inpointsand never needs this.