How to apply which.min over a list - r

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

Related

How to save a for-loop results

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

R: Using typeof() on something that looks like an array but gives integer?

I'm using Rstudio and I don't understand why my min.pair variable looks like a list or array made from a bunch of integers but identifies as an integer. I'm trying to count how many '2' there is using lenghts(), but it can't seem to work.
Thanks
two.dozen = matrix(sum.rolls, nrow = 25,ncol = 1000)
min.pair = apply(two.dozen, 1, min)
print(min.pair)
[1] 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2
typeof(min.pair)
[1] "integer"
You probably confuse lengths with the function length
x <- rep(2, 10)
x
# [1] 2 2 2 2 2 2 2 2 2 2
length will give you the amount of values in the list
length(x)
# [1] 10
lengths gives you the length of each item in the list, there is just one "2"
lengths(x)
# [1] 1 1 1 1 1 1 1 1 1 1
Lets create a nested list to illustrate the difference and use better.
y <- rep(list(list(1, 2)), 10)
y
# List of 10
# $ :List of 2
# ..$ : num 1
# ..$ : num 2
# $ :List of 2
# ..$ : num 1
# ..$ : num 2
# ...
length shows us that we have 10 lists in y
length(y)
# [1] 10
lengths shows us that we have two values in each of the 10 lists of y
lengths(y)
# [1] 2 2 2 2 2 2 2 2 2 2

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])

Convert a list of varying lengths into a dataframe

I am trying to convert a simple list of varying lengths into a data frame as shown below. I would like to populate the missing values with NaN. I tried using ldply, rbind, as.data.frame() but I failed to get it into the format I want. Please help.
x=c(1,2)
y=c(1,2,3)
z=c(1,2,3,4)
a=list(x,y,z)
a
[[1]]
[1] 1 2
[[2]]
[1] 1 2 3
[[3]]
[1] 1 2 3 4
Output should be:
x y z
1 1 1
2 2 2
NaN 3 3
NaN NaN 4
Using rbind.fill.matrix from "plyr" gets you very close to what you're looking for:
> library(plyr)
> t(rbind.fill.matrix(lapply(a, t)))
[,1] [,2] [,3]
1 1 1 1
2 2 2 2
3 NA 3 3
4 NA NA 4
This is a lot of code, so not as clean as Ananda's solution, but it's all base R:
maxl <- max(sapply(a,length))
out <- do.call(cbind, lapply(a,function(x) x[1:maxl]))
# out <- matrix(unlist(lapply(a,function(x) x[1:maxl])), nrow=maxl) #another way
out <- as.data.frame(out)
#names(out) <- names(a)
Result:
> out
V1 V2 V3
1 1 1 1
2 2 2 2
3 NA 3 3
4 NA NA 4
Note: names of the resulting df will depend on the names of your list (a), which doesn't currently have names.

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