I have some vector vect and I want to iterate over the row vectors vof a matrix and calculate:
cov(v, vect).
I tried:
for(vect in mat2) #where mat2 is a 215 by 31 matrix
However, each vector appeared to be a scalar with value 1.
How do I iterate over the row vectors of a matrix?
To make this even better, since I am interested in calculating the sum of cov(v, vect) where v is a row vector, how can I use the higher-order functions left-fold and right-fold
Are you looking for apply ?
apply(mat2, 1, function(v)cov(v,vect))
If I understand that vect is a separate vector from mat2:
apply(mat2, 1, function(v) cov(v, vect))
The apply function allows you to apply an arbitrary function over the rows (if the second argument is 1) or columns (if 2) or a higher dimension (if >2). It is also much faster than using a loop.
Related
Apologies in advance for what I know is simple. I just haven't been able to find the solution despite the 1000 search attempts and my rudimentary skills are not up to the challenge.
I have a list of matrices consisting of rows of integers. I can find row totals etc with (l)apply function etc. What I am stuck on however is removing an entire element if any of the rows fail a certain criteria, say a total of <500.
So in the below example:
x1 <- rnorm(50,5,0.32)
dim(x1) <- c(5,10)
x2 =rnorm(50,25,3.2)
dim(x2) <- c(5,10)
x3 =rnorm(50,25,3.2)
dim(x3) <- c(5,10)
x4=rnorm(50,0.8,0.1)
dim(x4) <- c(5,10)
x5=rep(NaN,50)
dim(x5) <- c(5,10)
list1<-list(x1,x2,x3,x4,x5)
If I sum each row in each element for a total:
goodbit <- lapply(list1, function (x) apply(x, 1, function(c) sum(c)))
I know I can filter out the elements with NAs:
list1nonas <- Filter(Negate(anyNA),list1)
But I am having a hard time extending that to criteria based on the row totals. For example how can I remove any element where any row total in that element is < 8.
(Element [[4]] in this example).
You can use rowSums. If we want to test whether there are any rowSums less than 8 in a given matrix x, we can do any(rowSums(x) < 8). Therefore the logical negation negation of this will return TRUE if none of the row sums are less than 8.
We can therefore put this inside an sapply to run the test on each matrix in our list, and return a logical vector.
Subsetting our original list by this vector returns a filtered list with only those matrices that have no row sums below 8.
list1[sapply(list1, function(x) !any(rowSums(x) < 8))]
Suppose I have a vector of length 10
vec <- c(10,9,8,7,6,5,4,3,2,1)
and I wanted to create a function that takes in a subset length value (say 3) and computes the squared inverse up to that length. I would like to compute:
10+(9/(2^2))+(8/(3^2))
which would be
vec[1]+(vec[2]/(2^2))+(vec[3]/(3^2))
but with a function that can take input of the subset length.
The only solution I can think of is a for loop, is there a faster more elegant solution in R?
Yes, you can use the fact that most operations in R are vectorised to do this without a loop:
vec <- c(10,9,8,7,6,5,4,3,2,1)
cum_inverse_square <- function(vec, n) {
sum(vec[1:n] / (1:n)^2)
}
cum_inverse_square(vec, 3) == 10+(9/(2^2))+(8/(3^2)) # TRUE
I want to test whether every element of data frame is greater than 0. If it is greater than zero it would we will be "buy" otherwise "sell". I used sapply. It allocated every value "sell". I used following code. Also recommend for loop solution.
df1<-sapply(df,function(x) ifelse(x>0,yes="buy",no="sell"))
If it is a matrix (or even data.frame), create a logical matrix by using the comparison operator. This gives a TRUE/FALSE logical matrix which is of value 1/0. If we add 1 to it, it changes to 2/1 and based on that index, we can replace values (in R, indexing starts from 1)
df[] <- c("sell", "buy")[(df >0) + 1]
Also, in the comments, it was recommended not to use sapply on matrix as matrix is a vector with dim attributes and the unit element is a single element (in data.frame, the unit is a column - so if we use sapply/lapply, it loops through columns). Here, it loops through element of the matrix. So, it may not be efficient. For matrix, apply with MARGINcan be used
df[] <- apply(df, 2, FUN = function(x) ifelse(x > 0, "sell", "buy"))
does anyone know a more efficient way to do the following? I have two matrices, one with integer values, the other with numeric. I also have a list containing integer vectors. I have a loop which sets the values of the numeric matrix to NA, when the integer values from the list are equal to the integer matrix. Then I get the row product and sum from the resulting matrix. Is there a way to avoid creating a copy of the numeric matrix each step? Or perhaps another approach all together? Thanks
mat1<-matrix(rpois(20*300000,6),20,300000)
mat2<-matrix(runif(20*300000),20,300000)
list1<-list(c(1,2,3),c(4,6),c(8,9,10,11))
results<-vector('numeric',length(list1))
start.time=Sys.time()
for(i in 1:length(list1)){
copy<-mat2
copy[mat1 %in% list1[[i]]]=NA
results[i]=sum(apply(copy,2,prod,na.rm=T))
}
print(Sys.time()-start.time)
#
Replacing your apply with colSums (assuming your numbers are positive, you'll need a bit more fiddling otherwise) gives me a close to 2x speed improvement:
for(i in 1:length(list1)){
copy<-mat2
copy[mat1 %in% list1[[i]]]=NA
results[i]=sum(exp(colSums(log(copy), na.rm = T)))
}
I have a matrix and a function that takes a vector and returns a matrix. I want to apply the function to all rows of the matrix and rbind all results together. For example
mat <- matrix(1:6, ncol=2)
f <- function (x) cbind(1:sum(x), sum(x):1)
do.call(rbind, apply(mat, 1, f))
This works perfectly since the returned matrices have different numbers of rows so apply returns a list. But if they happen to have the same numbers of rows this does not work anymore:
mat <- f(3)
apply(mat, 1, f)
apply returns a matrix from which I cannot get the result I want. Is it possible to force apply to return a list or is there another solution?
This is why I love the plyr package. It has a number of --ply functions that all work in the same way. The first letter corresponds to what you have as input and the second method corresponds to what you have as output (l for lists, a for arrays, d for data frames).
So the alply() function works similar to apply() but always returns a list:
alply(mat, 1, f)
You have to split matrix mat before applying function f.
list_result <- lapply(split(mat,seq(NROW(mat))),f)
matrix_result <- do.call(rbind,list_result)