How to save a for-loop results - r

I have this df:
dx <- structure(list(a = c(0.916290731874155, 2.89037175789616, -0.156004248476581,
-0.318453731118534, -2.07944154167984, 2.00533356952611, -1.24319351747922,
0.42744401482694, 1.29532258291416, -2.03292152604494, -0.606135803570316,
-0.693147180559945), b = c(0.550046336919272, 0.228258651980981,
-0.577634293438101, 0.135801541159061, 0.644357016390513, -2.30258509299405,
-0.0870113769896297, 1.71297859137494, 0.17958557697508, -1.65140211153313,
1.31218638896617, 0.282862786015832), c = c(0.0988458346366325,
-3.34403896782221, 1.99243016469021, -1.70474809223843, 2.62103882411258,
2.20727491318972, -1.40242374304977, -1.256836293883, -2.16905370036952,
2.91777073208428, 0.138586163286146, -0.946143695023836), d = c(0.268263986594679,
-2.83321334405622, 1.83258146374831, 1.15057202759882, 0.0613689463762919,
-2.23359222150709, 4.34236137828145, -3.44854350225935, 1.29098418131557,
-0.356674943938732, -0.21868920096483, -0.810930216216329), e = c(1.65140211153313,
0.220400065368459, -0.044951387862266, 0.0773866636154201, -1.49877234454658,
1.36219680954083, -0.295845383090942, -0.709676482511156, -0.916290731874155,
1.65822807660353, 0.451985123743057, -0.810930216216329)), class = "data.frame", row.names = 2:13)
and this script
output <- t(as.matrix(rep(NA, ncol=1)))
for(i in 1:12) {
output <- 2*dx[i,]
cmin <- which.min(output)
}
I need to save the result of cmin for each loop of i in another matrix. The result I expect is:
[1]
[1] 3
[2] 4
[3] 2
[4] 1
[5] 1
[6] 2
[7] 3
[8] 4
[9] 3
[10] 1
[11] 1
[12] 3
How can I do? Thank you!

Just use sapply() here, like this
as.vector(sapply(1:12, \(i) which.min(2*dx[i,])))
Output:
[1] 3 3 2 3 1 2 3 4 3 1 1 3

Just use
as.matrix(apply(dx , 1 , function(x) which.min(2*x)))
[,1]
1 3
2 3
3 2
4 3
5 1
6 2
7 3
8 4
9 3
10 1
11 1
12 3

Initialize a vector of length 12 and then assign the output to each element of the vector
cmin_out <- integer(12)
for(i in 1:12) {
output <- 2*dx[i,]
cmin_out[i] <- which.min(output)
}
cmin_out
[1] 3 3 2 3 1 2 3 4 3 1 1 3
The vector can be converted to a column matrix by wrapping with matrix
matrix(cmin_out)
This can be done in a efficient vectorized way in base R as well without having to loop - i.e. with max.col
max.col(-dx, 'first')
#[1] 3 3 2 3 1 2 3 4 3 1 1 3

Related

How to apply which.min over a list

Assume we have the following list :
list_1=list(c(115222.321776569, 37864639.6868223, 880844.193064039,
158574.408179366, 283899.102436544, 416531.537818319, 498992.661910475,
312537.505136515), c(498992.661910475, 33741049.3285334, 492180.657601543,
324174.022385466, 901091.893188845, 106068.170722435, 115222.321776569,
710087.526882994))
# list_1
[[1]]
[1] 115222.3 37864639.7 880844.2 158574.4 283899.1 416531.5 498992.7 312537.5
[[2]]
[1] 498992.7 33741049.3 492180.7 324174.0 901091.9 106068.2 115222.3 710087.5
It's possible to use which.min over columns ( like a matrix ) to obtain minima indices :
mapply(function(a, b) {which.min(c(a, b))}, a = list_1[[1]], b = list_1[[2]])
# Output :
[1] 1 2 2 1 1 2 2 1
I don't know how to obtain this when the list has a length that is greater than 2.
For example :
list_2=list(c(4,7,3),c(5,2,1),c(6,1,7))
# list_2
[[1]]
[1] 4 7 3
[[2]]
[1] 5 2 1
[[3]]
[1] 6 1 7
Output :
> 1 3 2
Thank you in advance for help !
You can try max.col + cbind
> max.col(-do.call(cbind, list_1))
[1] 1 2 2 1 1 2 2 1
and
> max.col(-do.call(cbind, list_2))
[1] 1 3 2
apply(do.call(cbind, list_1), 1, which.min)
Output
[1] 1 2 2 1 1 2 2 1

How to set each value of an xts object to the minimum of all previous values?

This does what I want, but I don't think it's the right way to do it...
for (n in 1:length(z)) {
if (z[n,] > min(z[1:n,]) ) {
z[n,] = min(z[1:n,])
}
}
Are you looking for cummin?
set.seed(1)
z <- sample(1:10)
z
# [1] 3 4 5 7 2 8 9 6 10 1
cummin(z)
# [1] 3 3 3 3 2 2 2 2 2 1

in R: How do I rank each individual data frame in a list of data frames?

I've simplified my problem conceptually as follows. I have a list (mylist) comprised of two data frames. I know how to reorder them both (say, on the 4th and 1st variable) using lapply:
mylist<-lapply(mylist, function(x) x[order(x[,4],x[,1]),])
Now I am trying to use lapply() and rank() to add a 5th column to each dataframe in the list, and populate the column with the rank (the rank within that dataframe, on the 4th variable say).
Ive tried dozens of permutations of this
mylist[,5]<-lapply(mylist, function(x) rank(x[,4], ties.method="first"))
nothing works right. Help! Thanks
> mylist
[[1]]
a b c d
1 1 4 7 A
2 2 5 8 A
3 3 6 9 B
[[2]]
a b c d
1 9 6 3 A
2 8 5 2 A
3 7 4 1 B
Well it couldn't be:
mylist[,5]<-lapply(mylist, function(x) rank(x[,4], ties.method="first"))
... because mylist[,5] doesn't make any sense. mylist you said was a two element list so it really didn't even have columns. So you need to loop over the elements and add the column to them individually:
mylist <-lapply(mylist, function(x) { rl <- rank( x[,4], ties.method="first")
x <- cbind( x, rl=rl)
x [ order(x['rl']) , ] } )
Your lapply returns the output of rank which is a vector. You need to append a column to each data.frame then return the data.frame
mylist <- list(data.frame(a = rnorm(5), b = rpois(5, 3)), data.frame(a = rnorm(5), b = rpois(5, 3)) )
mylist
## [[1]]
## a b
## 1 -1.31730854 4
## 2 0.04395243 1
## 3 0.15370905 0
## 4 -0.77556501 4
## 5 1.12879380 4
##
## [[2]]
## a b
## 1 -0.96314478 3
## 2 -0.54824004 6
## 3 0.34943917 1
## 4 -0.07077913 0
## 5 1.10519356 3
lapply(mylist, function(x) { x$c <- rank(x$b); x })
## [[1]]
## a b c
## 1 -1.31730854 4 4
## 2 0.04395243 1 2
## 3 0.15370905 0 1
## 4 -0.77556501 4 4
## 5 1.12879380 4 4
##
## [[2]]
## a b c
## 1 -0.96314478 3 3.5
## 2 -0.54824004 6 5.0
## 3 0.34943917 1 2.0
## 4 -0.07077913 0 1.0
## 5 1.10519356 3 3.5
Using the data provided by #JakeBurkhead, you can simply use transform
set.seed(123)
mylist <- list(data.frame(a = rnorm(5), b = rpois(5, 3)),
data.frame(a = rnorm(5), b = rpois(5, 3)) )
lapply(mylist, transform, c = rank(b, ties.method = "first"))
## [[1]]
## a b c
## 1 -0.560476 6 5
## 2 -0.230177 3 2
## 3 1.558708 4 4
## 4 0.070508 3 3
## 5 0.129288 1 1
## [[2]]
## a b c
## 1 1.28055 4 5
## 2 -1.72727 3 3
## 3 1.69018 3 4
## 4 0.50381 2 2
## 5 2.52834 1 1

Constant subset of a variable length list for some list[[x]] in R

Imagine the following data:
listA
[[1]]
[1] 1 2 3 4 5 6 7
[[2]]
[1] 1 2 3 4 5 6
[[3]]
[1] 1 2 3 4 5
How to select:
listA[[1:2]][1:4]
Using 1:2 there is not allowed, so is there any way to select these when it is known that this selection exists (both the 1:2 and 1:4 parts)?
What I would like returned:
listA
[[1]]
[1] 1 2 3 4
[[2]]
[1] 1 2 3 4
What about just using lapply,
R> l = list(A = 1:6, B=1:4, C = 1:5)
R> lapply(l[1:2], "[", 1:4)
$A
[1] 1 2 3 4
$B
[1] 1 2 3 4
You probably have to use lapply.
lapply(listA, function(x) x[1:4])
If your actual list is longer, you can access the first two elements of listA by listA[1:2]. So this should work:
lapply(listA[1:2], function(x) x[1:4])

How to output the data with different lengths

R Version 2.11.1 32-bit on Windows 7
I'm wondering if anyone else has encountered this question. I got several arrays with different lengths, and I want put them together to output. For example:
a=c(1,2,3);
b=c(2,4,1,6)
c=c(4,5,9,2,8)
ra=rank(a);#ra=1 2 3
rb=rank(b);#rb=2 3 1 4
rc=rank(c);#rc=2 3 5 1 4
then how to put ra, rb and rc together to be this:
1 2 3
2 3 1 4
2 3 5 1 4
Yes, list() may be help, but how could I save it to my PC.
I tred to use write.table(), but fail.
Transform list to matrix of strings.
a=c(1,2,3);
b=c(2,4,1,6)
c=c(4,5,9,2,8)
rlist <- lapply(list(a,b,c), rank)
m <- do.call(rbind, lapply(rlist,
function(x) paste(x,collapse=" ")
)
)
write.table(m,file="file_name")
Sounds like you want a list.
> list(ra, rb, rc)
[[1]]
[1] 1 2 3
[[2]]
[1] 2 3 1 4
[[3]]
[1] 2 3 5 1 4
> rlist <- lapply( list(a,b,c), rank)
> rlist
[[1]]
[1] 1 2 3
[[2]]
[1] 2 3 1 4
[[3]]
[1] 2 3 5 1 4

Resources