This might be a simple question, but I'm new to R and having trouble figuring it out. I've tried searching extensively for the answer and I cannot come up with it.
I have a dataframe that is 92:24. I would like to create an array that is (92, 2, 12) which is populated from the columns in the dataframe. I would like column 1 and 2 to be "stacked", columns 3 and 4, columns 5 and 6, and so on. The first dimension of the array should correspond to all the odd columns and the second dimension should correspond to all the even columns, with 92 rows and 12 columns in each of the 2 dimensions.
Any help would be greatly appreciated.
Thank you!
Maybe this does what you want.
First, create a data.frame with the appropriate dimensions.
dat <- as.data.frame(matrix(1:2208, ncol = 24))
Then, it's just a columns' shuffle and dim trick.
mat <- as.matrix(dat)
mat <- mat[, c((1:12)*2 - 1, (1:12)*2)]
dim(mat) <- c(92, 12, 2)
# See the first 5 rows
mat[1:5, , ]
Related
I'm trying to figure out a way how to fill blank cells in a row with previous existing data. I have an array of data with a customer ID-key I'd need to copy to some lines that don't automatically have the key ID due to gaps in source data.
Here's the situation. Gaps in data in Columns A:
Column A
Column B
Cell 1
Cell 2
Cell 4
Cell 6
Cell 7
Cell 8
Cell 10
Cell 12
This question comes in two parts. See the wished solution I tried to create below.
use:
=ARRAYFORMULA(IF(B2:B="",, VLOOKUP(ROW(A2:A), IF(A2:A<>"", {ROW(A2:A), A2:A}), 2, 1)))
update:
=ARRAYFORMULA(IF(B2:B="";; VLOOKUP(ROW(A2:A); IF(A2:A<>""; {ROW(A2:A)\ A2:A}); 2; 1)))
or:
=SCAN(; A2:INDEX(A:A; MAX(ROW(B:B)*(B:B<>""))); LAMBDA(a; b; IF(b=""; a; b)))
see: stackoverflow.com/questions/73767719
Use SCAN, like this
=SCAN(,A2:A7,LAMBDA(a,c,IF(c="",a,c)))
Since this is a very common question, I had also created a named function _FILL that solves this problem. You can import it from here.
And use it like this:
_FILL(vector, fill_mode)
// fill with previous non-empty -> fill_mode = 1
// fill with next non-empty -> fill_mode = -1
_FILL(A2:A7,1)
I have a 99x1 cell array and I would like to convert it into a 33x3 cell array for example.
I would like the first 3 rows of the 99x1 cell array to make up the first row in the 33x3 cell array and then the 3rd through 6th row in the 99x1 cell array to make up the second row in the 33x3 cell array.
I also need the data when being reshaped to go over column by column before it goes down. For example I would need:
1
2
3
4
to become
1, 2; 3, 4
not
1, 3; 2, 4
Help with this would be greatly appreciated
You can simply use the reshape-function. Since reshape(yourcell,[],3) would first fill the first column and then the second and so on instead of row-wise, you will need to combine it with the transpose operator .':
newcell=reshape(yourcell,3,[]).'
This way, you will first create a 3x33 cell using the reshape and then transform it into the desired 33x3 cell. The [] tells reshape to create as many columns as needed.
In R, I have a JAGS model output (made in parallel with jags.parfit from the dclone package) that is a list of six 2-dimensional matrices (corresponding to six chains each with 3000 reps) with column names equivalent to the indices of an array. The first digit has 3 unique values, the second 2000, the third 4, and the fourth 6.
head(colnames(m1[[1]]))
[1] "y.pred[1,1,1,1]" "y.pred[2,1,1,1]" "y.pred[3,1,1,1]" "y.pred[1,2,1,1]" "y.pred[2,2,1,1]" "y.pred[3,2,1,1]"
I want to convert this long-form matrix into an array with 5 dimensions which correspond to the 3000 reps as row and the 4 indices from the column names as new columns. This array will have the following dimensions:
dim(m1.array)
[1] 3000 3 2000 4 6
Is there a relatively straightforward way to do this?
UPDATE
Based on the below suggestion, I was able to convert each matrix to the expected array with the following code:
m1.arrayList <- lapply(m1, function(x) array(x, dim = c(3000, 3, 2000, 4, 6)))
I was then able to convert the list of 5-dim arrays into a 6-dim array with:
m1.array <- simplify2array(m1.arrayList)
The drop function and the drop argument in the [ subsetting function both work completely or not at all. If I have, for example, a four-dimensional array whose 2nd and 4th dimensions are length 1 only, then drop will return a 2-dimensional array with both these dimensions removed. How can I drop the 4th dimension but not the 2nd?
e.g.
arr <- array(1:4, c(2, 1, 2, 1))
drop(arr)
arr[,,, 1, drop = TRUE]
The reason for doing this in my case is so that I can set up the array correctly for binding to other arrays in abind. In the example given, one might wish to bind arr[,,, 1] to a 3-dimensional array along dimension 2.
I've thought about it some more and come up with a solution. The below function defines the new target dimensions and fits the data into a new array of those dimensions. omit is a vector of dimension numbers never to drop.
library("abind")
drop.sel <- function(x, omit){
ds <- dim(x)
dv <- ds == 1 & !(seq_along(ds) %in% omit)
adrop(x, dv)
}
If anyone thinks they have a more elegant solution, I'd be happy to see it.
I'm trying to find values in a multidimensional array which are only in one column. I can find the correct values when searching the entire multidimensional array. But if I try and limit the find in the multidimensional array to say just the second column the values are not the expected ones.
example of code and correct output:
A = [2 4 6; 8 10 12]
A(:,:,2) = [5 7 9; 11 13 15]
A(:,:,3) = [55 4 55; 167 167 154]
[row,col,page]=ind2sub(size(A), find(A(:,1,:)==4))
row =1,1
col =2,2
page =1,3
But If I try and limit the find to just the second column using these commands
[row,col,page]=ind2sub(size(A), find(A(:,2,:)==4))
row =1,1
col =1,3
page =1,1
I get values that are different from the expected ones. I'm trying to limit the multidimensional find to search all pages, all rows, and one specific column. The output should be the same as the first example. How can I fix this?
With [m,n,o]=size(A), you are using A(:,2,:)==4 which is a matrix n*1*o. ind2sub expects a n*m*o matrix. Typical approach is using a mask:
mask=false(size(A));
mask(:,2,:)=true;
[i,j,k]=ind2sub(size(A), find((A(:,:,:)==4)&mask))
The mask selects the entries you are interested in.
Daniel's answer works by defining a mask and then searching throughout the whole array with that mask applied. The following limits the search to the desired column, and thus may be faster for large arrays:
col = 2; %// desired column
[row, page] = ind2sub([size(A,1) size(A,3)], find(A(:,col,:)==4));
If you need col as a vector the same size as row and page, you can of course achieve it with col = repmat(col,size(row)).