Convert vector into a triangular matrix - vector

I have a vector of 874! elements, which I want to turn into a triangular matrix (i.e. the top right hand corner of a square matrix).
Example Input:
1
2
3
4
5
6
7
8
9
10
Example Output:
1 2 4 7
3 5 8
6 9
10
Blanks could be filled with NAs. I'd prefer if the matrix were this way around.

I don't know which programming language do you want to use neither do I understand which order do you want your numbers to be stored in.
You should consider that having N elements, if you want to generate an square matrix its dimensions (n rows and columns) are given by:
N = (n*(n+1))/2
So a first approach (you should consider if your input vector has x^2/2 elements) in Python could be:
from math import sqrt
x = range(1,25+1) # This is your input vector
N = len(x)
#N = (n*(n+1))/2 # Number of elements being stored in a triangular matrix.
n = (-1.0+sqrt(1.0+8.0*N))/2.0 # Solve the equation given by the previous relation.
n = int(round(n)) # Making it integer...
while (n*(n+1))/2 < N: # ... losing precission so we should use the first n being able ...
if (n*(n+1))/2 < N: # ... to store your vector is used.
n += 1
res = [[0]*n for i in xrange(n)] # Here, we create a n*n matrix filled with zeros.
x = x[::-1] #Reverse the input so it can be consumed using pop (O(1) each extraction)
for j in xrange(n): # Fill the empty matrix following the triangular pattern and using...
if not x:
break
for i in xrange(j+1):
if not x:
break
res[i][j] = x.pop() # The elements from your input vector.
for row in res: # Let's print the result!
print(row)
The idea is to consume x filling the square matrix (res) with is values in the right order. This can easily done once you now your target matrix dimesions.

Related

How to add a constant in a for loop by keeping the original matrix in each iteration?

For example,
x<-matrix(c(1,2,3,4),2,2)
1 2
3 4
I want to add the constant "c" to each element of the matrix separately like this.
Iteration 1
1+c 2
3 4
Iteration 2
1 2+c
3 4
Iteration 3
1 2
3+c 4
Iteration 4
1 2
3 4+c
I have tried the following R code, but it retains the updated value while performing second iteration.
x= matrix of order nxm
for(i in 1:r)
{
for(j in 1:c)
{
x[i,j]=x[i,j]+c
print(x)
}
}
In this code the values getting updated and printing the updated value for each iteration.
Please help me... Thanks in Advance.
R prefers array operations.
Any matrix x is just an array of its entries, laid out column by column. You may successively add the constant c to the first, second, third, ... entry to copies of x, so that the original x remains unchanged. Do this by constructing arrays of the same length as x with all zero entries except for c in the desired location. The code shown at the end of this post does this by concatenating a bunch of zeros, c, and more zeros so that c appears in position i:
c(rep(0,i-1), cnst, rep(0,n-i)
If you loop with i=1, 2, 3, etc, the results will work down through each column of x, moving left to right. To do the operations in the order presented in the question, which works through each row, moving top to bottom, simply apply the procedure to the transpose of x and transpose the outputs.
Even for large matrices, this approach of adding an entire array is at least twice as fast on my system as adding c just to the i position of a copy of x.
Here is R code for the general procedure. It works on any non-empty matrix x. Beware: the output consists of length(x) copies of x and therefore can be quite large. In this example--which takes about a second to run on my system--x has 10,000 entries and therefore the output has 100,000,000 entries. You might want to test it on smaller matrices first!
x <- matrix(1:(100^2), 100) # Any nonempty matrix
cnst <- 1 # Value to add successively to each term in `x`
#
# The algorithm begins here.
#
n <- length(x)
lapply(1:n, function(i) matrix(as.vector(x)+c(rep(0,i-1),cnst,rep(0,n-i)), nrow(x)))
You just need to make a copy of the matrix:
x_safely_stored <- matrix of order nxm
for(i in 1:r) {
for(j in 1:c) {
x <- x_safely_stored
x[i,j]=x[i,j]+c
print(x)
}
}

Randomly sampling from each element of a vector

Let's say I have a numeric vector X
X <- c(1,42,1,23,5,7)
I would like to create another vector Y with the same number of elements, each of which is a randomly generated whole number from a sequence in which 1 is the lower bound and the element in X is the upper bound e.g for Y[2] the number would be a randomly generated number selected from between 1 and 42 and for Y[4] the number would be randomly selected from between 1 and 23.
I have tried to use the apply function to do this
Y<-apply(C, 1, sample)
but I am having no luck and generating the error message
Error in apply(X, 1, sample) : dim(X) must have a positive length1,
sample
Is there a better way to do this?
You can't use apply for a vector, but for multidimensional objects only (e.g., matrices). You have to use sapply instead. Futhermore, you need the argument size = 1 since you want to sample one value for each entry of X.
sapply(X, sample, size = 1)
[1] 1 7 1 16 3 6

Convert a one column matrix to n x c matrix

I have a (nxc+n+c) by 1 matrix. And I want to deselect the last n+c rows and convert the rest into a nxc matrix. Below is what I've tried, but it returns a matrix with every element the same in one row. I'm not sure why is this. Could someone help me out please?
tmp=x[1:n*c,]
Membership <- matrix(tmp, nrow=n, ncol=c)
You have a vector x of length n*c + n + c, when you do the extract, you put a comma in your code.
You should do tmp=x[1:(n*c)].
Notice the importance of parenthesis, since if you do tmp=x[1:n*c], it will take the range from 1 to n, multiply it by c - giving a new range and then extract based on this new range.
For example, you want to avoid:
(1:100)[1:5*5]
[1] 5 10 15 20 25
You can also do without messing up your head with indexing:
matrix(head(x, n*c), ncol=c)

Distances between two lists of position vectors

I am trying to get a matrix that contains the distances between the points in two lists.
The vector of points contain the latitude and longitude, and the distance can be calculated between any two points using the function distCosine in the geosphere package.
> Points_a
lon lat
1 -77.69271 45.52428
2 -79.60968 43.82496
3 -79.30113 43.72304
> Points_b
lon lat
1 -77.67886 45.48214
2 -77.67886 45.48214
3 -77.67886 45.48214
4 -79.60874 43.82486
I would like to get a matrix out that would look like:
d_11 d_12 d_13
d_21 d_22 d_23
d_31 d_32 d_33
d_41 d_42 d_43
I am struggling to think of a way to generate the matrix without just looping over Points_a and Points_b and calculating each combination, can anyone suggest a more elegant solution?
You can use this:
outer(seq(nrow(Points_a)),
seq(nrow(Points_b)),
Vectorize(function(i, j) distCosine(Points_a[i,], Points_b[j,]))
)
(based on tip by #CarlWitthoft)
According to the desired output you post, maybe you'll want the transpose t() of this, or simply replace _a with _b above.
EDIT: some explanation:
seq(nrow(Points_x)): creates a sequence from 1 to the number of rows of Points_x;
distCosine(Points_a[i,], Points_b[j,]): expression to compute the distance between points given by row i of Points_a and row j of Points_b;
function(i, j): makes the above an unnamed function in two parameters;
Vectorize(...): ensure that, given inputs i and j of length greater than one, the unnamed function above is called only once for each element of the vectors (see this for more info);
outer(x, y, f): creates "expanded" vectors x and y such that all combinations of its elements are present, and calls f using this input (see link above). The result is then reassembled into a nice matrix.

Select matrix column (resp. row) as Nx1 (resp. 1xD) matrix, as opposed to vector

Let X be an N by D matrix. Selecting a submatrix of size n by d returns a matrix of those dimensions unless at least one of n and d equals 1, in which case we get a vector instead. Interestingly, R still returns a matrix of the correct dimensions even if one of n and d are 0, and the other not 1.
Now, if we are certain that n!=1, then executing cbind(X[row.subset,col.subset]) will return a matrix of the correct dimensions regardless of whether d==1 or not (here n=length(row.subset) and d=length(col.subset)). If we are certain that d!=1, then we can use rbind(...). But if both n and d can be 1, neither approach will work since we could accidentally turn a row into a column or vice versa.
As far as I can tell, one way to always get a matrix of the right dimensions is to call matrix(X[row.subset,col.subset],nrow=n,ncol=d). However, it doesn't feel like that should be the right way to go about it, plus I'm not confident that there is no performance penalty. Is there a more "native" solution?
Here's a working example:
N <- 6
D <- 3
X <- matrix(rnorm(N*D),ncol=D)
dim(X[1:2,1:2]) #returns 2 2
dim(X[1:2,1]) #returns NULL, this is a vector
dim(cbind(X[1:2,1])) #returns 2 1
dim(cbind(X[1,1:2])) #returns 2 1, but we'd like it to be 1 2
dim(rbind(X[1,1:2])) #returns 1 2
dim(rbind(X[1:2,1])) #returns 1 2, but we'd like it to be 2 1
row.subset <- 1:4
col.subset <- 2
#I _think_ this is always correct, but it's verbose:
matrix(X[row.subset,col.subset],nrow=length(row.subset),ncol=length(col.subset))
Thanks in advance.
If you don't want to simplify matrix subsets to vectors just tell [ not to drop dimensions:
> dim(X[1:2,1, drop=FALSE])
[1] 2 1
> dim(X[1,1:2, drop=FALSE])
[1] 1 2
See ?"[" for details.

Resources