Im trying to expand the size of multidimensional array.
More particullary I have an 10x3x3 (rowsxcolumnsxmatrix) array and I want to expand it to become an 20x3x3 array.
I want to keep my current data in the first 10 rows and just resize their rows so I can add more data. Ideally the new rows should have 0s.
I can do this with loops but Im wondering if there is a function that can do the whole process automatically.
Thanks in advance
You can use the library abind.
library(abind)
v1=numeric(10)
v2=numeric(3)
a=array(c(v1, v2), dim = c(10, 3, 3))
res <- abind(originalArray, a, along = 1)
Related
I have two lists and I want to subtract one list element wise with the other, in order to replicate a Matlab function bsxfun(#minus, lt, lt2). The two lists look something like the below (edit: now works without pracma package):
# Code
# First list
lt = c(list())
# I use these lines to pre-dim the list...
lt[[1]] = c(rep(list(1)))
lt[[2]] = c(rep(list(1)))
# ... such that I can add matrices it this way:
lt[[1]][[1]] = matrix(c(3),nrow=1, ncol=1,byrow=TRUE)
lt[[2]][[1]] = matrix(c(1),nrow=1, ncol=1, byrow=TRUE)
# Same with the second list:
lt2 = c(list())
lt2[[1]] = c(rep(list(1)))
lt2[[2]] = c(rep(list(1)))
lt2[[1]][[1]] = matrix(c(2,2,2),nrow=3, ncol=1,byrow=TRUE)
lt2[[2]][[1]] = matrix(c(1,1,1),nrow=3, ncol=1,byrow=TRUE)
Element wise subtraction would mean that that each row of an element of lt2 would be subtracted
by the respective element of the object lt, i.e., lt2[[1]][[1]] each row by 3, resulting in t(c(-1 -1 -1)).... and lt2[[2]][[1]] = t(c(0,0,0)) by 1 ... It is important to me that the list structure is maintained in the results.
Now I tried using lapply(lt2,"-",lt) but it does not work. Any suggestions?
I suspect you are looking for something like this skeleton code which subtracts 2 lists element-wise...
x <- list(1,2,3)
y <- list(4,5,6)
mapply('-', y, x, SIMPLIFY = FALSE)
but as noted, you need 2 identical lists (or at least R's recycling algorithms must make sense) as for example...
z <- list(4,5,6,7,8,9)
mapply('-',z,x,SIMPLIFY = FALSE)
You might be looking for something like this where you subtract a constant from each member of the list...
mapply('-',y,2, SIMPLIFY= FALSE)
I figured it out - I had another mistake in the question :/
Changing the second class as.numeric worked
lt3 = lapply(lt2[[1]],"-",as.numeric(lt[[1]]))
I'm rather new to R and there's probably a really easy way to do this, but I can not figure this out for the life of me. I am trying to convert a mutli-layer TIF file into a multi-channel TIF file and to do that I need to basically turn a list of multiple 2-dimensional arrays into one 3-dimensional array.
I attempted to simply split up the 9 different arrays in the list, create a new list with 3 dimensions and insert the arrays into the new list, but it keeps telling me that there is a "wrong number of subscripts".
multiChannelFile = array(c(960, 1280, 9))
for (row in 1:960) {
for (column in 1:1280) {
for (channel in 1:9) {
multiChannelFile[row, column, channel] = tifFile[channel][[1]][row, column]
}
}
}
You can use simplify2array():
multiChannelFile <- simplify2array(tifFile)
And of course, as soon as I posted this question, I figured it out.
Changing multiChannelFile = array(c(960, 1280, 9)) to multiChannelFile = array(dim = c(960, 1280, 9)) did the trick.
You can blend the list to a vector by unlist() and reset the dimension.
array(unlist(tifFile), dim = c(dim(tifFile[[1]]), length(tifFile)))
I am running a for loop to fill dynamically a dataframe (I know a baby seal dies somewhere because I am using a for loop)
I have something like this in mind (the 5 is a placeholder for a function that returns a scalar):
results<-data.frame(matrix(NA, nrow = length(seq(1:10)), ncol =
length(seq(1:10))))
rows<-data.frame(matrix(NA, nrow = 1, ncol = 1))
for (j in seq(1:10)){
rows<-data.frame()
for (i in seq(1:10)){
rows<-cbind(rows,5)
}
results<-cbind(results,rows)
}
I get the following error message with my approach above.
Error in match.names(clabs, names(xi)) :
names do not match previous names
Is there an easier way?
Dynamically filling an object using a for loop is fine - what causes problems is when you dynamically build an object using a for loop (e.g. using cbind and rbind rows).
When you build something dynamically, R has to go and request new memory for the object in each loop, because it keeps increasing in size. This causes a for loop to slow down with every iteration as the object gets bigger.
When you create the object beforehand (e.g. a data.frame with the right number of rows and columns), and fill it in by index, the for loop doesn't have this problem.
One final thing to keep in mind is that for data.frames (and matrices) each column is stored as a vector in memory – so its usually more efficient to fill these in one column at a time.
With all that in mind we can revise your code as follows:
results <- data.frame(matrix(NA, nrow = length(seq(1:10)),
ncol = length(seq(1:10))))
for (rowIdx in 1:nrow(results)) {
for (colIdx in 1:ncol(results)) {
results[rowIdx, colIdx] <- 5 # or whatever value you want here
}
}
Not sure what is your intention. Now keeping your intention and way of implementation a way to fix the problem to change for-loop so that rows is initialized with 1st value. The second for-loop should be from seq(2:10).
The error is occurring because attempting to cbind a blank data.frame with valid value.
for (j in seq(1:10)){
rows<-data.frame(5) #Initialization with 1st value
for (i in seq(2:10)){ #Loop 2nd on wards.
rows<-cbind(rows,5)
}
results<-cbind(results,rows)
}
Or how to split a vector into pairs of contiguous members and combine them in a list?
Supose you are given the vector
map <-seq(from = 1, to = 20, by = 4)
which is
1 5 9 13 17
My goal is to create the following list
path <- list(c(1,5), c(5,9), c(9,13), c(13,17))
This is supposed to represent the several path segments that the map is sugesting us to follow. In order to go from 1 to 17, we must first take the first path (path[1]), then the second path (path[2]), and all the way to the end.
My first attempt lead me to:
path <- split(aux <- data.frame(S = map[-length(map)], E = map[-1]), row(aux))
But I think it would be possible without creating this auxiliar data frame
and avoiding the performance decrease when the initial vector (the map) is to big. Also, it returns a warning message which is quite alright, but I like to avoid them.
Then I found this here on stackoverflow (not exactly like this, this is the adapted version for my problem):
mod_map <- c(map, map[c(-1,-length(map))])
mod_map <- sort(mod_map)
split(mod_map, ceiling(seq_along(mod_map)/2))
which is a simpler solution, but I have to use this modified version of my map.
Pherhaps I'm asking too much as I already got two solutions. But, could it be possible to have a third one, so that I don't have so use data frames as in my first solution and can use the original map, unlike my second solution?
We can use Map on the vector ('map' - better not to use function names - it is a function from purrr) with 1st and last element removed and concatenate elementwise
Map(c, map[-length(map)], map[-1])
Or as #Sotos mentioned, split can be used which would be faster
split(cbind(map[-length(map)], map[-1]), seq(length(map)-1))
How do I create a vector like this:
a = [a_1;a_2;...,a_n];
aNew = [a;a.^2;a.^3;...;a.^T].
Is it possible to create aNew without a loop?
So you want different powers of a, all strung out into a vector? I would create an array, where each column of the array is a different power of a. Then string it out into a vector. Something like this...
aNew = bsxfun(#power,a,1:T);
aNew = aNew(:);
This does what you want, in a simple, efficient way. bsxfun is a more efficient way of writing the expansion than are other methods, such as repmat, ndgrid and meshgrid.
The code I wrote does assume that a is a column vector, as you have constructed it.
The idea is to use meshgrid to create two arrays of size n x T:
[n_mesh, t_mesh] = meshgrid(a, 1:T);
Now n_mesh is an array where each row is a duplicate of a, and t_mesh is an array where each column is 1:T.
Now you can use an element-wise operation on them to create what you need:
aNew = n_mesh .^ t_mesh;