R colon operator on list of matrices - r

I've created a list of matrices in R. In all matrices in the list, I'd like to "pull out" the collection of matrix elements of a particular index. I was thinking that the colon operator might allow me to implement this in one line. For example, here's an attempt to access the [1,1] elements of all matrices in a list:
myList = list() #list of matrices
myList[[1]] = matrix(1:9, nrow=3, ncol=3, byrow=TRUE) #arbitrary data
myList[[2]] = matrix(2:10, nrow=3, ncol=3, byrow=TRUE)
#I expected the following line to output myList[[1]][1,1], myList[[2]][1,1]
slice = myList[[1:2]][1,1] #prints error: "incorrect number of dimensions"
The final line of the above code throws the error "incorrect number of dimensions."
For reference, here's a working (but less elegant) implementation of what I'm trying to do:
#assume myList has already been created (see the code snippet above)
slice = c()
for(x in 1:2) {
slice = c(slice, myList[[x]][1,1])
}
#this works. slice = [1 2]
Does anyone know how to do the above operation in one line?
Note that my "list of matrices" could be replaced with something else. If someone can suggest an alternative "collection of matrices" data structure that allows me to perform the above operation, then this will be solved.
Perhaps this question is silly...I really would like to have a clean one-line implementation though.

Two things. First, the difference between [ and [[. The relevant sentence from ?'[':
The most important distinction between [, [[ and $ is that the [ can
select more than one element whereas the other two select a single
element.
So you probably want to do myList[1:2]. Second, you can't combine subsetting operations in the way you describe. Once you do myList[1:2] you will get a list of two matrices. A list typically has only one dimension, so doing myList[1:2][1,1] is nonsensical in your case. (See comments for exceptions.)
You might try lapply instead: lapply(myList,'[',1,1).

If your matrices will all have same dimension, you could store them in a 3-dimensional array. That would certainly make indexing and extracting elements easier ...
## One way to get your data into an array
a <- array(c(myList[[1]], myList[[2]]), dim=c(3,3,2))
## Extract the slice containing the upper left element of each matrix
a[1,1,]
# [1] 1 2

This works:
> sapply(myList,"[",1,1)
[1] 1 2
edit: oh, sorry, I see almost the same idea toward the end of an earlier answer. But sapply probably comes closer to what you want, anyway

Related

for-loop code array my result by binary system

In R:
I tried to make a list of dataframes arrayed by the names of dataframes (p_text_tm_list_1, p_text_tm_list_2, ..., p_text_tm_list_892)
by using loop (for i in 1:892)
but the result of that codes was arrayed by binary (1,10,100,101...) system as you can see in the second captured console screen.
Why was the result arrayed by binary system?
How can I array the dataframe in decimal system?
Thanks for reading.
Here is a way to solve your problem.
First, create the list p_text_top10_list without resorting to assign. The list is created with its final length in order not to keep extending it,which is ineffective.
p_text_top10_list <- vector("list", length = length(p_text_tm_list))
for(i in seq_along(p_text_tm_list)){
p_text_top10_list[[i]] <- head(p_text_tm_list[[i]], 10)
}
Another much simpler way is to use lapply.
p_text_top10_list <- lapply(p_text_tm_list, head, 10)
That's it. This one-liner does exactly the same as the previous for loop.
Now assign the names with 3 digits to have them in the proper order.
names(p_text_top10_list) <- sprintf("p_text_top10_list_%03d", seq_along(p_text_top10_list))

Create a list where each element is a pair of contiguous members from given vector

Or how to split a vector into pairs of contiguous members and combine them in a list?
Supose you are given the vector
map <-seq(from = 1, to = 20, by = 4)
which is
1 5 9 13 17
My goal is to create the following list
path <- list(c(1,5), c(5,9), c(9,13), c(13,17))
This is supposed to represent the several path segments that the map is sugesting us to follow. In order to go from 1 to 17, we must first take the first path (path[1]), then the second path (path[2]), and all the way to the end.
My first attempt lead me to:
path <- split(aux <- data.frame(S = map[-length(map)], E = map[-1]), row(aux))
But I think it would be possible without creating this auxiliar data frame
and avoiding the performance decrease when the initial vector (the map) is to big. Also, it returns a warning message which is quite alright, but I like to avoid them.
Then I found this here on stackoverflow (not exactly like this, this is the adapted version for my problem):
mod_map <- c(map, map[c(-1,-length(map))])
mod_map <- sort(mod_map)
split(mod_map, ceiling(seq_along(mod_map)/2))
which is a simpler solution, but I have to use this modified version of my map.
Pherhaps I'm asking too much as I already got two solutions. But, could it be possible to have a third one, so that I don't have so use data frames as in my first solution and can use the original map, unlike my second solution?
We can use Map on the vector ('map' - better not to use function names - it is a function from purrr) with 1st and last element removed and concatenate elementwise
Map(c, map[-length(map)], map[-1])
Or as #Sotos mentioned, split can be used which would be faster
split(cbind(map[-length(map)], map[-1]), seq(length(map)-1))

Getting elements of a list in R

This is my problem:
There is a predefined list named gamma with three entries: gamma$'2' is 2x2 matrix gamma$'3' a 3x3 matrix and gamma$'4' a 4x4 matrix. I would like to have function that returns the matrix I need:
GiveMatrix <- function(n) {
gamma.list <- #init the list of matrices
gamma.list$n # return the list entry named n
Since n is not a character, the last line does not work. I tried gamma.list$paste(n)and gamma.list$as.character(n)but both did not work. Is there a function that converts nto the right format? Or is there maybe a much better way? I know, I am not really good in R.
You need to use:
gamma.list[[as.character(n)]]
In your example, R is looking for a entry in the list called n. When using [[, the contents of n is used, which is what you need.
I've found it!
gamma.list[as.character(n)] is the solution I needed.

How to access single elements in a table in R

How do I grab elements from a table in R?
My data looks like this:
V1 V2
1 12.448 13.919
2 22.242 4.606
3 24.509 0.176
etc...
I basically just want to grab elements individually. I'm getting confused with all the R terminology, like vectors, and I just want to be able to get at the individual elements.
Is there a function where I can just do like data[v1][1] and get the element in row 1 column 1?
Try
data[1, "V1"] # Row first, quoted column name second, and case does matter
Further note: Terminology in discussing R can be crucial and sometimes tricky. Using the term "table" to refer to that structure leaves open the possibility that it was either a 'table'-classed, or a 'matrix'-classed, or a 'data.frame'-classed object. The answer above would succeed with any of them, while #BenBolker's suggestion below would only succeed with a 'data.frame'-classed object.
There is a ton of free introductory material for beginners in R: CRAN: Contributed Documentation
?"[" pretty much covers the various ways of accessing elements of things.
Under usage it lists these:
x[i]
x[i, j, ... , drop = TRUE]
x[[i, exact = TRUE]]
x[[i, j, ..., exact = TRUE]]
x$name
getElement(object, name)
x[i] <- value
x[i, j, ...] <- value
x[[i]] <- value
x$i <- value
The second item is sufficient for your purpose
Under Arguments it points out that with [ the arguments i and j can be numeric, character or logical
So these work:
data[1,1]
data[1,"V1"]
As does this:
data$V1[1]
and keeping in mind a data frame is a list of vectors:
data[[1]][1]
data[["V1"]][1]
will also both work.
So that's a few things to be going on with. I suggest you type in the examples at the bottom of the help page one line at a time (yes, actually type the whole thing in one line at a time and see what they all do, you'll pick up stuff very quickly and the typing rather than copypasting is an important part of helping to commit it to memory.)
Maybe not so perfect as above ones, but I guess this is what you were looking for.
data[1:1,3:3] #works with positive integers
data[1:1, -3:-3] #does not work, gives the entire 1st row without the 3rd element
data[i:i,j:j] #given that i and j are positive integers
Here indexing will work from 1, i.e,
data[1:1,1:1] #means the top-leftmost element

how do I get the difference between two R named lists?

OK, I've got two named lists, one is "expected" and one is "observed". They may be complex in structure, with arbitrary data types. I want to get a new list containing just those elements of the observed list that are different from what's in the expected list. Here's an example:
Lexp <- list(a=1, b="two", c=list(3, "four"))
Lobs <- list(a=1, c=list(3, "four"), b="ni")
Lwant <- list(b="ni")
Lwant is what I want the result to be. I tried this:
> setdiff(Lobs, Lexp)
[[1]]
[1] "ni"
Nope, that loses the name, and I don't think setdiff pays attention to the names. Order clearly doesn't matter here, and I don't want a=1 to match with b=1.
Not sure what a good approach is... Something that loops over a list of names(Lobs)? Sounds clumsy and non-R-like, although workable... Got any elegant ideas?
At least in this case
Lobs[!(Lobs %in% Lexp)]
gives you what you want.
OK, I found one slightly obtuse answer, using the plyr package:
> Lobs[laply(names(Lobs), function(x) !identical(Lobs[[x]], Lexp[[x]]))]
$b
[1] "ni"
So, it takes the names of the array from the observed function, uses double-bracket indexing and the identical() function to compare the sub-lists, then uses the binary array that results from laply() to index into the original observed function.
Anyone got a better/cleaner/sexier/faster way?

Resources