Tapply over matrix using matrix math - r

All,
I have the following code, I'd like to make it generalized for more clusters, ie C clusters. Is there a way to do this without a loop? Here, the rows of X correspond to variables x1,x2, and T is a linear transformation of X. Thanks.
X=matrix(c(2,3,4,5,6,7,8,9,2,3,4,5,6,7,8,9),2)
cluster=c(1,1,1,0,0,0,0,0)
T=matrix(c(1,2,2,1),2)
f<-function(x) max(eigen(t(x)%*%x)$values)
f(T%*%X[,cluster==0])+f(T%*%X[,cluster==1])
## [1] 1134.87
I was thinking of
sum(tapply(X,cluster,function(x) f(T%*%x)))
but I get this error, I think because tapply takes a vector vs matrix:
> sum(tapply(X,cluster,function(x) f(T%*%x)))
Error in tapply(X, cluster, function(x) f[x]) :
arguments must have same length
Here is an answer with a for loop, if you can find something without a loop please let me know
#
c=length(levels(factor(cluster)))
cluster=factor(cluster,labels=1:c)
s=0
for (i in 1:c){
s=s+f(T%*%X[,cluster==c])
}
s
## [1] 1134.872

Could try doing this via tapply
tapply(seq_len(ncol(X)), cluster, function(x) f(T%*%X[, x]))
# 0 1
# 3840.681 1238.826

Related

How to create a sequentially ordered list in R with lapply and replicate?

I have been trying to avoid for loops in R. However, I have had issues with using lapply with replicate in that the lists I obtain have ordering that are not sequential. For example, the following code:
lapply(1:5, function(x) replicate(100, rnorm(x), simplify = F))
creates 100 instances of each: rnorm(1), rnorm(2), ..., rnorm(5).
This is much faster than using a for loop. However, the resulting list indices I get are:
.........
[[5]][[98]]
[1] -0.87686000 -0.82373642 -0.05671333 -2.24652788 -1.43497760
[[5]][[99]]
[1] -1.6935926 0.4753606 0.1190997 0.1464246 0.8604974
[[5]][[100]]
[1] 0.68414921 0.32183115 1.23681540 -1.34076190 -0.08467215
while what I want is:
[[1]] -0.87686000
[[2]] -0.8237
......
[[500]] 1.236
Is there a way to modify the code above so that it order the list from 1 to 500? Thanks!
You can just call unlist() on the result, e.g.:
unlist(lapply(1:5, function(x) replicate(100, rnorm(x))))
Though note that you'll get an atomic vector of length 1500 -- since you're generating 1+2+3+4+5=15 random values 100 times.
That what you're aiming for?
If the goal is to get 500 total values, where the mean changes from 1 to 5 within each iteration, then you can just say:
unlist(lapply(1:5, function(x) replicate(100, rnorm(1, mean=x))))
You can see the upward trend with, e.g.:
values <- unlist(lapply(1:5, function(x) replicate(100, rnorm(1, mean=x))))
plot(seq_along(values), values)

solving conditional symbolic equation in R

Here are my vectors. Note that the vector m consists of unknown value x.
r=c(1, 3, 5)
p=c(5, 3, 1)
s=c(1, 3, 5)
m=c(x, x, x)
How I can solve the following conditional vector equation in R?
I'd like to find the value of x which makes the sum of elements in the vector of p*(s-m)*(ifelse((s-m)<0, r, 6-r)) zero.
sum(p*(s-m)*(ifelse((s-m)<0, r, 6-r)))=0
I was told that rSymPy might handle this but I don't think this works for the vector equation. Any thoughts or suggestions?
In fact, I was able to get the answer in Excel using "goal seek" but would like to get R commands for solving this.
Excel does numeric calculations, not symbolic, so we assume that a numeric solution is really what you want. In that case it can be solved numerically like this:
f <- function(x) sum(p*(s-x)*(ifelse((s-x)<0, r, 6-r)))^2
optimize(f, range(s))
giving:
$minimum
[1] 2.4667
$objective
[1] 3.1554e-30

How to compute summation in r

My R code:
((x[1]-xm)^2)+((x[2]-xm)^2)+((x[3]-xm)^2)+((x[4]-xm)^2)+((x[5]-xm)^2)+((x[6]-xm)^2)
This computation would be much easier if i formulated the problem as a summation. How do I do that in r? Something like:
sum((x[i]-xm)^2) for i=1 to i=6?
x is a data frame.
Without reading all the responses in this thread, there is a really easy way to do summations in R.
Modify the following two lines as needed to accommodate a matrix or other type of vector:
i <- 0:5; sum(i^2)
Use i for your index when accessing a position in your vector/array.
Note that i can be any vector.
You need to use sum(), example below:
IndexStart <- 1
x <- seq(IndexStart, 6, 1)
xm <- 1
result1 <- ((x[1]-xm)^2)+((x[2]-xm)^2)+((x[3]-xm)^2)+((x[4]-xm)^2)+((x[5]-xm)^2)+((x[6]-xm)^2)
print(result1)
# [1] 55
result2 <- sum((x-xm)^2) # <- Solution
print(result2)
# [1] 55

How to make a matrix from a given vector by using for loop

I am trying to make a $n\times 4$ matrix by retrieving the n-th four elements in a given vector. Since I am new to R, don't know how to use loop functions properly.
My code is like
x<-runif(150,-2,2)
x1<-c(0,0,0,0,x)
for (i in 0:150)
{ai<-x1[1+i,4+i]
}
However, I got: Error in x1[1 + i, 4 + i] : incorrect number of dimensions.
I also want to combine these ai into a matrix, and each ai will be the i+1-th row of the matrix. Guess I should use the cbind function?
Any help will be appreciated. Thanks in advance.
You can do this directly with the matrix command:
x <- 1:36
xmat<-matrix(x,nr=9,byrow=TRUE)
May be this helps:
n <- length(x1)-1
res <- sapply((4:n)-3, function(i) x1[(i+3):i])
dim(res)
#[1] 4 150

R - Apply function on every row, with data from the row

Is there a faster way to do this:
for (i in 1:nrow(dataframe))
{
dataframe$results <- with(dataframe, myownfunction(column1[i],
column2[i], column3[i], column4[i], column5[i], column6[i])
}
myownfunction finds implied volatility using uniroot(), but when uniroot does not find a solution it stops (usually because there some faults in the data), and the loop stops. Is there a way to make the function just output NA if it gets an error from uniroot and continue with the next row?
regards.
Part1: It's very likely that you could succeed with:
ave( dataframe[, c("column1", column2", column3", "column4", "column5", "column6")], myownfunction)
Part2: If you modified the function to test for failure with try and returned NA when it fails you can fill in the missing data in the result properly.
You seem to have to questions:
1) Returning a value if failure happens. As posted already, look at failwith in the plyr package. It does exactly this.
2) Speed up the for loop. Have you tried using mapply? It is a multivariate apply that applies a function to the each element of each argument simultaneously. So
mapply(myfunc, column1, column2, column3, column4)
(along with modifying myfunc to use failwith) would do the sort of thing you are looking for.
The plyr version of mapply is mdply if you prefer.
Got this from another forum, I like it more than the previous options:
R> M <- matrix(1:6, nrow=3, byrow=TRUE)
R> M
[,1] [,2]
[1,] 1 2
[2,] 3 4
[3,] 5 6
R> apply(M, 1, function(x) 2*x[1]+x[2])
[1] 4 10 16

Resources