How can I coerce "list" to S4 "List" (reproducible example is available)?
1
0
Entering edit mode
@jurat-shahidin-9488
Last seen 18 months ago
Chicago, IL, USA

Hi everyone:

Is there any way to coerce simple list-like object "list" to S4 "List" object? Apparently, I used nested-lapply on my functions, and I checked its return type as "list". I want "List" like objects instead. Is that possible to do such coercion in R? if answer is yes, how can I do that ? Thanks

Here is the reproducible example to understand the problem that I stated :

foo <- GRanges(
seqnames=Rle(c("chr1", "chr2", "chr3", "chr4"), c(3, 2, 1, 2)),
ranges=IRanges(seq(1, by=9, len=8), seq(7, by=9, len=8)),
rangeName=letters[seq(1:8)], score=sample(1:20, 8, replace = FALSE))

bar <- GRanges(
seqnames=Rle(c("chr1", "chr2", "chr3","chr4"), c(4, 3, 1, 1)),
ranges=IRanges(seq(2, by=5, len=9), seq(4, by=5, len=9)),
rangeName=letters[seq(1:9)], score=sample(1:20, 9, replace = FALSE))

moo <- GRanges(
seqnames=Rle(c("chr1", "chr2", "chr3","chr4"), c(3, 4, 2,1)),
ranges=IRanges(seq(5, by=7, len=10), seq(8, by=7, len=10)),
rangeName=letters[seq(1:10)], score=sample(1:20, 10, replace = FALSE))

# hitIndex;

grl <- GRangesList(bar, moo)
res <- lapply(grl, function(ele_) {
tmp <- as(findOverlaps(foo, ele_), "List")
})

obj.ov <- lapply(res, function(ele_) {
re <- lapply(grl, function(obj) {
id0 <- as(which.max(extractList(obj$score, ele_)), "List") id0 <- id0[!is.na(id0)] }) re <- re[!duplicated(re)] }) I want to coerce obj.ov to S4 "List" ?. Any way to do this in R? Any possible approach, ideas, are appreciated. Best regards; Jurat coercion data manipulation s4vectors List • 740 views ADD COMMENT 0 Entering edit mode Same question on Biostars: https://www.biostars.org/p/200238/ ADD REPLY 2 Entering edit mode @gordon-smyth Last seen 4 hours ago WEHI, Melbourne, Australia Reading help("List-class") reveals ​as(res, "List") ADD COMMENT 0 Entering edit mode Dear Gordon: I tried this way, but it won't work, as.obj.ov can't be expandable as obj.ov like hit-index vector,plus it gave me this : as.obj.ov <- as(obj.ov, "List") > as(obj.ov, "List") List of length 2 Here is further explanation that substantiate my attempt: bar.ovHit <- res[] bar.ov_keepOne <- as(which.max(extractList(bar$score, bar.ovHit)), "List")
bar.ov.idx <- bar.ov_keepOne[!is.na(bar.ov_keepOne)]
bar.ov <- unlist(extractList(seq_along(bar), bar.ovHit)[bar.ov.idx])
bar[bar.ov]

Actually, I have to add my possible next step after I got res, now I inserted that part as well, please re run the scripts. I am expecting obj.ov as S4 "List", and obj.ov must be expandable as it was. Any possible solution for this kind of coercion. Thank you

1
Entering edit mode

Hi Jurat,

Gordon is right. as(res, "List") is the way to coerce an ordinary list to List. It works as expected. Note that res is a nested list structure (the list elements in it are IntegerList objects). Maybe by coercing res to List you were expecting to get something like an IntegerListList object? There is no such class in Bioconductor. This is why you get a generic List object instead. Technically it's a SimpleList object. If you look at its internal representation, it's just a wrapper around an ordinary list. Therefore you won't get any benefits in terms of performance by using this SimpleList object vs using an ordinary list.

As a general advice: it's hard to compute efficiently on nested list structures so it's better if you can avoid them. That often requires taking a completely different approach to how you implement things. This can be hard too. We can help but we need to know a little bit more about what you're trying to achieve.

BTW, the last part of the code in your original post gives me an error:

> obj.ov <- lapply(res, function(ele_) {
+   re <- lapply(grl, function(obj) {
+     id0 <- as(which.max(extractList(obj$score, ele_)), "List") + id0 <- id0[!is.na(id0)] + }) + re <- re[!duplicated(re)] + }) Error: subscript contains out-of-bounds indices Cheers, H. ADD REPLY 0 Entering edit mode Dear Herve: Thank you for your comprehensive explanation for this issue. Yes, using nestled lapply is not good idea, I just proved this and got my solution finally. Therefore, in my solution, there is no need to use nested lapply, no need of using such coercion, I was wrong about the concepts. once again thanks for you are giving me underlying principle behind coercion in Bioconductor. regarding the error, please try this modification : obj.ov <- lapply(grl, function(ele_) { res <- as(findOverlaps(foo, ele_), "List") idx <- as(which.min(extractList(ele_$score, res)), "List")
idx <- idx[!is.na(idx)]
res[idx]
})

If you are able give any suggestion to optimize above code to make more compatible and efficient, I will be grateful for your effort. Thank you

Jurat