Replace values along the first of n dimensions of an array
EDIT: I have simplified the example and the functions following the comment of @jdorbes. Hope this improves the post.
I have a series of N-dimensional array that I need to "rotate" along their first dimension (e.g. in a 2d matrix, switching between each other the first and the second half of the columns).
For example considering a 3D case I can define my array as:
field <- array(1:32, c(4, 4, 2))
I developed a very basic and dimension-dependent function that achieves the goal. The same operation can be done of course also with head
and tail
but I found out that this is the faster way:
rotate.test <- function(field) {
xxx <- field
dims <- length(dim(xxx))
if (dims == 2) { # for x,y data
ll <- length(field[, 1])
field[(ll * 0.5 + 1 ):ll, ] <- xxx[1:(ll * 0.5), ]
field[1:(ll * 0.5), ] <- xxx[(ll * 0.5 + 1):ll, ]
}
if (dims == 3) { # for x,y,t data
ll <- length(field[, 1, 1])
field[(ll * 0.5 + 1 ):ll, , ] <- xxx[1:(ll * 0.5), , ]
field[1:(ll * 0.5), , ] <- xxx[(ll * 0.5 + 1):ll, , ]
}
return(field)
}
The result reads as:
> rotate.test(field)
, , 1
[,1] [,2] [,3] [,4]
[1,] 3 7 11 15
[2,] 4 8 12 16
[3,] 1 5 9 13
[4,] 2 6 10 14
, , 2
[,1] [,2] [,3] [,4]
[1,] 19 23 27 31
[2,] 20 24 28 32
[3,] 17 21 25 29
[4,] 18 22 26 30
This can be further generalized for N-dimensional data, but I guess you see that it is very clumsy.
Following this post Select along one of n dimensions in array I found out that I can generalize it introducing a very useful call to the do.call
function:
array_indexing <- function(field, dim, value, drop = FALSE) {
indices <- rep(list(bquote()), length(dim(field)))
indices[[dim]] <- value
out <- do.call("[",c(list(field), indices, list(drop = drop)))
return(out)
}
Then using abind
rotate.evo <- function(field) {
require("abind")
xdim <- 1
ll <- dim(field)[xdim]
firstchunk <- array_indexing(field, xdim, (ll * 0.5 + 1):ll)
secondchunk <- array_indexing(field, xdim, 1:(ll * 0.5))
out <- abind(firstchunk, secondchunk, along = 1)
return(out)
}
However, the benchmarking (done with rbenchmark
) is awful likely due to the call to abind
instead of the simpler index replacement.
test replications elapsed relative user.self sys.self
2 rotate.evo(field) 1000 0.547 6.36 0.542 0.005
1 rotate.test(field) 1000 0.086 1.00 0.069 0.016
user.child sys.child
2 0 0
1 0 0
Here it comes my question: is there any way to generalize the index replacement as done by the array_indexing
function? In other words, is there any way to perform this switching in a fast and robust way without writing ad-hoc cases for each dimension? What I am trying to find out is exists in R a method to generalize the replacement of some array index along a defined dimension.
I know this may sound as a weird request, but it will be great if I can avoid to load extra packages. This code is included in a online tool that should be lighter as possible (actually, I am trying to get rid of abind too!)
Thanks for any hint, and please ask if any part of my explanation is incomplete.
Best,
Paolo
r multidimensional-array
add a comment |
EDIT: I have simplified the example and the functions following the comment of @jdorbes. Hope this improves the post.
I have a series of N-dimensional array that I need to "rotate" along their first dimension (e.g. in a 2d matrix, switching between each other the first and the second half of the columns).
For example considering a 3D case I can define my array as:
field <- array(1:32, c(4, 4, 2))
I developed a very basic and dimension-dependent function that achieves the goal. The same operation can be done of course also with head
and tail
but I found out that this is the faster way:
rotate.test <- function(field) {
xxx <- field
dims <- length(dim(xxx))
if (dims == 2) { # for x,y data
ll <- length(field[, 1])
field[(ll * 0.5 + 1 ):ll, ] <- xxx[1:(ll * 0.5), ]
field[1:(ll * 0.5), ] <- xxx[(ll * 0.5 + 1):ll, ]
}
if (dims == 3) { # for x,y,t data
ll <- length(field[, 1, 1])
field[(ll * 0.5 + 1 ):ll, , ] <- xxx[1:(ll * 0.5), , ]
field[1:(ll * 0.5), , ] <- xxx[(ll * 0.5 + 1):ll, , ]
}
return(field)
}
The result reads as:
> rotate.test(field)
, , 1
[,1] [,2] [,3] [,4]
[1,] 3 7 11 15
[2,] 4 8 12 16
[3,] 1 5 9 13
[4,] 2 6 10 14
, , 2
[,1] [,2] [,3] [,4]
[1,] 19 23 27 31
[2,] 20 24 28 32
[3,] 17 21 25 29
[4,] 18 22 26 30
This can be further generalized for N-dimensional data, but I guess you see that it is very clumsy.
Following this post Select along one of n dimensions in array I found out that I can generalize it introducing a very useful call to the do.call
function:
array_indexing <- function(field, dim, value, drop = FALSE) {
indices <- rep(list(bquote()), length(dim(field)))
indices[[dim]] <- value
out <- do.call("[",c(list(field), indices, list(drop = drop)))
return(out)
}
Then using abind
rotate.evo <- function(field) {
require("abind")
xdim <- 1
ll <- dim(field)[xdim]
firstchunk <- array_indexing(field, xdim, (ll * 0.5 + 1):ll)
secondchunk <- array_indexing(field, xdim, 1:(ll * 0.5))
out <- abind(firstchunk, secondchunk, along = 1)
return(out)
}
However, the benchmarking (done with rbenchmark
) is awful likely due to the call to abind
instead of the simpler index replacement.
test replications elapsed relative user.self sys.self
2 rotate.evo(field) 1000 0.547 6.36 0.542 0.005
1 rotate.test(field) 1000 0.086 1.00 0.069 0.016
user.child sys.child
2 0 0
1 0 0
Here it comes my question: is there any way to generalize the index replacement as done by the array_indexing
function? In other words, is there any way to perform this switching in a fast and robust way without writing ad-hoc cases for each dimension? What I am trying to find out is exists in R a method to generalize the replacement of some array index along a defined dimension.
I know this may sound as a weird request, but it will be great if I can avoid to load extra packages. This code is included in a online tool that should be lighter as possible (actually, I am trying to get rid of abind too!)
Thanks for any hint, and please ask if any part of my explanation is incomplete.
Best,
Paolo
r multidimensional-array
It's very difficult to tell from your post what the expected effect of your custom function is meant to be. Could you provide an example output using a simpler input, perhaps an array such asarray(1:32, c(4, 4, 2))
?
– jdobres
Jan 2 at 17:53
@jdobres I tried to simplify the whole story. I am trying to find out if exists in R a method to generalize the replacement of a part of an array through indexing along a defined dimension without writing a dimension-dependent code.
– Paolo Davini
Jan 3 at 7:44
add a comment |
EDIT: I have simplified the example and the functions following the comment of @jdorbes. Hope this improves the post.
I have a series of N-dimensional array that I need to "rotate" along their first dimension (e.g. in a 2d matrix, switching between each other the first and the second half of the columns).
For example considering a 3D case I can define my array as:
field <- array(1:32, c(4, 4, 2))
I developed a very basic and dimension-dependent function that achieves the goal. The same operation can be done of course also with head
and tail
but I found out that this is the faster way:
rotate.test <- function(field) {
xxx <- field
dims <- length(dim(xxx))
if (dims == 2) { # for x,y data
ll <- length(field[, 1])
field[(ll * 0.5 + 1 ):ll, ] <- xxx[1:(ll * 0.5), ]
field[1:(ll * 0.5), ] <- xxx[(ll * 0.5 + 1):ll, ]
}
if (dims == 3) { # for x,y,t data
ll <- length(field[, 1, 1])
field[(ll * 0.5 + 1 ):ll, , ] <- xxx[1:(ll * 0.5), , ]
field[1:(ll * 0.5), , ] <- xxx[(ll * 0.5 + 1):ll, , ]
}
return(field)
}
The result reads as:
> rotate.test(field)
, , 1
[,1] [,2] [,3] [,4]
[1,] 3 7 11 15
[2,] 4 8 12 16
[3,] 1 5 9 13
[4,] 2 6 10 14
, , 2
[,1] [,2] [,3] [,4]
[1,] 19 23 27 31
[2,] 20 24 28 32
[3,] 17 21 25 29
[4,] 18 22 26 30
This can be further generalized for N-dimensional data, but I guess you see that it is very clumsy.
Following this post Select along one of n dimensions in array I found out that I can generalize it introducing a very useful call to the do.call
function:
array_indexing <- function(field, dim, value, drop = FALSE) {
indices <- rep(list(bquote()), length(dim(field)))
indices[[dim]] <- value
out <- do.call("[",c(list(field), indices, list(drop = drop)))
return(out)
}
Then using abind
rotate.evo <- function(field) {
require("abind")
xdim <- 1
ll <- dim(field)[xdim]
firstchunk <- array_indexing(field, xdim, (ll * 0.5 + 1):ll)
secondchunk <- array_indexing(field, xdim, 1:(ll * 0.5))
out <- abind(firstchunk, secondchunk, along = 1)
return(out)
}
However, the benchmarking (done with rbenchmark
) is awful likely due to the call to abind
instead of the simpler index replacement.
test replications elapsed relative user.self sys.self
2 rotate.evo(field) 1000 0.547 6.36 0.542 0.005
1 rotate.test(field) 1000 0.086 1.00 0.069 0.016
user.child sys.child
2 0 0
1 0 0
Here it comes my question: is there any way to generalize the index replacement as done by the array_indexing
function? In other words, is there any way to perform this switching in a fast and robust way without writing ad-hoc cases for each dimension? What I am trying to find out is exists in R a method to generalize the replacement of some array index along a defined dimension.
I know this may sound as a weird request, but it will be great if I can avoid to load extra packages. This code is included in a online tool that should be lighter as possible (actually, I am trying to get rid of abind too!)
Thanks for any hint, and please ask if any part of my explanation is incomplete.
Best,
Paolo
r multidimensional-array
EDIT: I have simplified the example and the functions following the comment of @jdorbes. Hope this improves the post.
I have a series of N-dimensional array that I need to "rotate" along their first dimension (e.g. in a 2d matrix, switching between each other the first and the second half of the columns).
For example considering a 3D case I can define my array as:
field <- array(1:32, c(4, 4, 2))
I developed a very basic and dimension-dependent function that achieves the goal. The same operation can be done of course also with head
and tail
but I found out that this is the faster way:
rotate.test <- function(field) {
xxx <- field
dims <- length(dim(xxx))
if (dims == 2) { # for x,y data
ll <- length(field[, 1])
field[(ll * 0.5 + 1 ):ll, ] <- xxx[1:(ll * 0.5), ]
field[1:(ll * 0.5), ] <- xxx[(ll * 0.5 + 1):ll, ]
}
if (dims == 3) { # for x,y,t data
ll <- length(field[, 1, 1])
field[(ll * 0.5 + 1 ):ll, , ] <- xxx[1:(ll * 0.5), , ]
field[1:(ll * 0.5), , ] <- xxx[(ll * 0.5 + 1):ll, , ]
}
return(field)
}
The result reads as:
> rotate.test(field)
, , 1
[,1] [,2] [,3] [,4]
[1,] 3 7 11 15
[2,] 4 8 12 16
[3,] 1 5 9 13
[4,] 2 6 10 14
, , 2
[,1] [,2] [,3] [,4]
[1,] 19 23 27 31
[2,] 20 24 28 32
[3,] 17 21 25 29
[4,] 18 22 26 30
This can be further generalized for N-dimensional data, but I guess you see that it is very clumsy.
Following this post Select along one of n dimensions in array I found out that I can generalize it introducing a very useful call to the do.call
function:
array_indexing <- function(field, dim, value, drop = FALSE) {
indices <- rep(list(bquote()), length(dim(field)))
indices[[dim]] <- value
out <- do.call("[",c(list(field), indices, list(drop = drop)))
return(out)
}
Then using abind
rotate.evo <- function(field) {
require("abind")
xdim <- 1
ll <- dim(field)[xdim]
firstchunk <- array_indexing(field, xdim, (ll * 0.5 + 1):ll)
secondchunk <- array_indexing(field, xdim, 1:(ll * 0.5))
out <- abind(firstchunk, secondchunk, along = 1)
return(out)
}
However, the benchmarking (done with rbenchmark
) is awful likely due to the call to abind
instead of the simpler index replacement.
test replications elapsed relative user.self sys.self
2 rotate.evo(field) 1000 0.547 6.36 0.542 0.005
1 rotate.test(field) 1000 0.086 1.00 0.069 0.016
user.child sys.child
2 0 0
1 0 0
Here it comes my question: is there any way to generalize the index replacement as done by the array_indexing
function? In other words, is there any way to perform this switching in a fast and robust way without writing ad-hoc cases for each dimension? What I am trying to find out is exists in R a method to generalize the replacement of some array index along a defined dimension.
I know this may sound as a weird request, but it will be great if I can avoid to load extra packages. This code is included in a online tool that should be lighter as possible (actually, I am trying to get rid of abind too!)
Thanks for any hint, and please ask if any part of my explanation is incomplete.
Best,
Paolo
r multidimensional-array
r multidimensional-array
edited Jan 3 at 7:40
Paolo Davini
asked Jan 2 at 16:52


Paolo DaviniPaolo Davini
213
213
It's very difficult to tell from your post what the expected effect of your custom function is meant to be. Could you provide an example output using a simpler input, perhaps an array such asarray(1:32, c(4, 4, 2))
?
– jdobres
Jan 2 at 17:53
@jdobres I tried to simplify the whole story. I am trying to find out if exists in R a method to generalize the replacement of a part of an array through indexing along a defined dimension without writing a dimension-dependent code.
– Paolo Davini
Jan 3 at 7:44
add a comment |
It's very difficult to tell from your post what the expected effect of your custom function is meant to be. Could you provide an example output using a simpler input, perhaps an array such asarray(1:32, c(4, 4, 2))
?
– jdobres
Jan 2 at 17:53
@jdobres I tried to simplify the whole story. I am trying to find out if exists in R a method to generalize the replacement of a part of an array through indexing along a defined dimension without writing a dimension-dependent code.
– Paolo Davini
Jan 3 at 7:44
It's very difficult to tell from your post what the expected effect of your custom function is meant to be. Could you provide an example output using a simpler input, perhaps an array such as
array(1:32, c(4, 4, 2))
?– jdobres
Jan 2 at 17:53
It's very difficult to tell from your post what the expected effect of your custom function is meant to be. Could you provide an example output using a simpler input, perhaps an array such as
array(1:32, c(4, 4, 2))
?– jdobres
Jan 2 at 17:53
@jdobres I tried to simplify the whole story. I am trying to find out if exists in R a method to generalize the replacement of a part of an array through indexing along a defined dimension without writing a dimension-dependent code.
– Paolo Davini
Jan 3 at 7:44
@jdobres I tried to simplify the whole story. I am trying to find out if exists in R a method to generalize the replacement of a part of an array through indexing along a defined dimension without writing a dimension-dependent code.
– Paolo Davini
Jan 3 at 7:44
add a comment |
0
active
oldest
votes
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54010187%2freplace-values-along-the-first-of-n-dimensions-of-an-array%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
0
active
oldest
votes
0
active
oldest
votes
active
oldest
votes
active
oldest
votes
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54010187%2freplace-values-along-the-first-of-n-dimensions-of-an-array%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
It's very difficult to tell from your post what the expected effect of your custom function is meant to be. Could you provide an example output using a simpler input, perhaps an array such as
array(1:32, c(4, 4, 2))
?– jdobres
Jan 2 at 17:53
@jdobres I tried to simplify the whole story. I am trying to find out if exists in R a method to generalize the replacement of a part of an array through indexing along a defined dimension without writing a dimension-dependent code.
– Paolo Davini
Jan 3 at 7:44