Replace values along the first of n dimensions of an array












0















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










share|improve this question

























  • 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
















0















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










share|improve this question

























  • 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














0












0








0








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










share|improve this question
















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






share|improve this question















share|improve this question













share|improve this question




share|improve this question








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 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



















  • 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

















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












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
});


}
});














draft saved

draft discarded


















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
















draft saved

draft discarded




















































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.




draft saved


draft discarded














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





















































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







Popular posts from this blog

MongoDB - Not Authorized To Execute Command

How to fix TextFormField cause rebuild widget in Flutter

Npm cannot find a required file even through it is in the searched directory