Supposed I have the following list:
x <- list(rbind(c(1,1,1,0),c(1,0,1,0), c(1,0,0,0)), c(1,1,0,1), c(1,2,3,4))
I know how to use unlist(lapply(x, "[[", 4)), but it works only when they are vectors inside the list.
If I want to extract the last column of each list, how can I do this ?
The return should be c(0, 1, 4).
Thank you
The second and third list elements are just vectors. Also, your description of extracting the last column and expected result is confusing. If you want to extract the last element.
sapply(x, function(.x) tail(c(.x),1))
#[1] 0 1 4
Or you could convert the vector elements to matrix and then extract the columns.
x1 <- lapply(x, function(.x) if(is.vector(.x)) t(.x) else (.x))
x2 <- lapply(x1, `[`,,4)
x2
#[[1]]
#[1] 0 0 0
#[[2]]
#[1] 1
#[[3]]
#[1] 4
unique(unlist(x2))
#[1] 0 1 4
Also, your code is only extracting the elements at specific positions and not the columns. For example:
z <- list(matrix(c(1:6), ncol=3), matrix(c(1:12), ncol=4))
lapply(z, `[[`, 3) #extracts the third element and not the third column
#[[1]]
#[1] 3
#[[2]]
#[1] 3
whereas,
lapply(z, `[`, ,3)
#[[1]]
#[1] 5 6
#[[2]]
#[1] 7 8 9
I would use
unlist(lapply(x, function(y) if(is.vector(y)) y[length(y)] else unique(y[,ncol(y)])))
#[1] 0 1 4
Related
a1 <- c("COL8A1/PRG4/DPT/ASPN/PODN/CCN1/BGN/MXRA5/MGP/COL16A1/MFAP5/THBS1/MATN2/AEBP1/MFAP4/SRPX/COL14A1/FGL2/ABI3BP/THBS2/LAMA4/COL8A2/FMOD/CTHRC1/COL12A1/OGN/PRELP/LTBP2/ANOS1")
a2 <- c("DPYSL3/CTSG/CCN5/CCN1/BGN/PCOLCE2/SLIT2/CCDC80/RSPO3/CFH/LYVE1/SFRP1/SLIT3/THBS1/SULF1/GPNMB/CCN2/SELP/THBS2/SPOCK2/RSPO1/PRELP/TGFBR3/LTBP2/LPL/HBEGF/ANOS1/NRP2/TGFBR2/CLEC3B/LXN/THBS4/SERPINE2/POSTN")
a3 <- c("CTSG/CCN5/CCN1/PCOLCE2/SLIT2/CCDC80/RSPO3/CFH/SFRP1/SLIT3/THBS1/GPNMB/CCN2/SELP/THBS2/RSPO1/PRELP/TGFBR3/LTBP2/LPL/HBEGF/ANOS1/NRP2/CLEC3B/LXN/THBS4/SERPINE2/POSTN/COMP/FBLN7/ECM2/SMOC2/SOD3")
a4 <- c("PDLIM3/MYH11/CNN1/SORBS1/FLNC/MYOM1/NEXN/ADD2/MYOZ3/MYLK/TAGLN/SHANK3/SYNE3/GSN/FAM107A/COBLL1/AIF1/LMOD1/TPM2/FLNA/SNCA/SPTBN1/TNNT3/VASH2/GMFG/S100A4/ENC1/KLHL4/WASF3/LMOD3/CORO1C/HCLS1/ABLIM2/TPM1/CALD1/ABLIM3/LIMA1/SVIL/FXYD5/NOS3/TNS1/SMTN/PLS3/MYH10/ENAH/WAS/EPB41L2/PLEC/MYO18A/ANG/MYO1C/MAP1A/MYO1F/EPB41L3/MTSS1/MAP1B/SNTA1/DMD/CNN3/PKNOX2")
b <- c(a1,a2,a3,a4)
If I have a special element,'CCN1', how can I identify which element of vector b has 'CCN1', and the location in each vector,a1,a2,a3 and a4. I can see 'CCN1' is the sixth one of a1, the forth one of a2, the third one of a3.
To identify which element of vector b has CCN1 grep or grepl coluld be used:
grep("CCN1", b)
#[1] 1 2 3
grepl("CCN1", b)
#[1] TRUE TRUE TRUE FALSE
To get the position the string need to be split on / using strsplit and than again grep could be used.
lapply(strsplit(b, "/", TRUE), grep, pattern="CCN1")
#[[1]]
#[1] 6
#
#[[2]]
#[1] 4
#
#[[3]]
#[1] 3
#
#[[4]]
#integer(0)
library(stringr)
str_which("CCN1", unlist(str_split(a1, "/")))
[1] 6
Or more generally
library(purrr)
library(stringr)
map(b, function(x) str_which("CCN1", unlist(str_split(x, "/"))))
[[1]]
[1] 6
[[2]]
[1] 4
[[3]]
[1] 3
[[4]]
integer(0)
I have a list of a list with high complicated data. I would like to compare the values of each list and extract the smallest values. For simplicity, I provide a similar example.
s <- c(1,2,3)
ss <- c(4,5,6)
S <- list(s,ss)
h <- c(4,8,7)
hh <- c(0,3,4)
H <- list(h,hh)
HH <- list(S,H)
I would like to compare the element of each list with the element of the corresponding list and extract the smallest values. For example, the following are the values of HH list.
> HH
[[1]]
[[1]][[1]]
[1] 1 2 3
[[1]][[2]]
[1] 4 5 6
[[2]]
[[2]][[1]]
[1] 4 8 7
[[2]][[2]]
[1] 0 3 4
Now, I would like to compare
[[1]]
[[1]][[1]]
[1] 1 2 3
with
[[2]]
[[2]][[1]]
[1] 4 8 7
For example, 1 < 4, so I will select 1. For the second element, 2 < 8, so I will select 2. So, I would like to compare the elements of [[1]][[1]] with the elements of [[2]][[1]], and [[1]][[2]] with [[2]][[2]].
Then, I would like to print the name of the list. For example,
I expected to have similar to the following:
1 < 4, the first element of the first model is selected.
We could use a general solution (i.e. if there are many list elements) transpose from purrr to rearrange the list elements, and then use max.col to get the index
library(magrittr)
library(purrr)
HH %>%
transpose %>%
map(~ .x %>%
invoke(cbind, .) %>%
multiply_by(-1) %>%
max.col )
#[[1]]
#[1] 1 1 1
#[[2]]
#[1] 2 2 2
Or using base R
do.call(Map, c(f = function(...) max.col(-1 * cbind(...)), HH))
#[[1]]
#[1] 1 1 1
#[[2]]
#[1] 2 2 2
Maybe you can try this -
Map(function(x, y) as.integer(x > y) + 1, HH[[1]], HH[[2]])
#[[1]]
#[1] 1 1 1
#[[2]]
#[1] 2 2 2
This gives the position of the element selected.
This question already has answers here:
Given a vector, return a list of all combinations up to size n
(3 answers)
Closed 4 years ago.
I failed at searching for how to do this specific transformation. Does anyone have a smart way to achieve this? sorry if I missed an obvious answer somewhere. thanks
# start with a single vector
1:3
# achieve this desired structure, containing every combination
# from combn( x , 1 ) thru combn( x , length( x ) )
list(
1 ,
2 ,
3 ,
c( 1 , 2 ) ,
c( 1 , 3 ) ,
c( 2 , 3 ) ,
c( 1 , 2 , 3 )
)
Loop through the sequence of values, get the combn of the vector with m specified as the sequence values, split by 'col', flatten the nested list to a list of vectors with do.call(c and unname it
unname(do.call(c, lapply(1:3, function(x) {
x1 <- combn(1:3, x)
split(x1, col(x1))})))
#[[1]]
#[1] 1
#[[2]]
#[1] 2
#[[3]]
#[1] 3
#[[4]]
#[1] 1 2
#[[5]]
#[1] 1 3
#[[6]]
#[1] 2 3
#[[7]]
#[1] 1 2 3
Or as #IceCreamToucan mentioned in the comments
do.call(c, lapply(1:3, function(x) combn(1:3, x, simplify = FALSE)))
In R, I am calling unlist on a list to convert to a vector. However, some of my list elements are empty, and hence returns integer(0). The unlist() function by default drops this. How can I return a vector that has NA where the list is empty? I have created a reproducible example:
> ex.list <- list()
> ex.list[[1]] <- integer(0)
> ex.list[[2]] <- c(1,2,3)
> ex.list
[[1]]
integer(0)
[[2]]
[1] 1 2 3
> unlist(ex.list)
[1] 1 2 3
Thanks.
A way of doing it is to use function is.na<-.
is.na(ex.list) <- lengths(ex.list) == 0
ex.list
#[[1]]
#[1] NA
#
#[[2]]
#[1] 1 2 3
Then you will have a NA where the list had a length of 0.
unlist(ex.list)
#[1] NA 1 2 3
We can do an assignment based on the length of the list element i.e. if it is equal to 0, assign as NA
ex.list[lengths(ex.list)==0] <- NA
ex.list
#[[1]]
#[1] NA
#[[2]]
#[1] 1 2 3
You could also try the one-liner
unlist(lapply(ex.list, function (x) ifelse(length (x) > 0, x, NA)))
Assume that this is my list
a <- list(c(1,2,4))
a[[2]] <- c(2,10,3,2,7)
a[[3]] <- c(2, 2, 14, 5)
How do I subset this list to exclude all the 2's. How do I obtain the following:
[[1]]
[1] 1 4
[[2]]
[1] 10 3 7
[[3]]
[1] 14 5
My current solution:
for(j in seq(1, length(a))){
a[[j]] <- a[[j]][a[[j]] != 2]
}
However, this approach feels a bit unnatural. How would I do the same thing with a function from the apply family?
Thanks!
lapply(a, function(x) x[x != 2])
#[[1]]
#[1] 1 4
#
#[[2]]
#[1] 10 3 7
#
#[[3]]
#[1] 14 5
Using lapply you can apply the subset to each vector in the list. The subset used is, x[x != 2].
Or use setdiff by looping over the list with lapply
lapply(a, setdiff, 2)
#[[1]]
#[1] 1 4
#[[2]]
#[1] 10 3 7
#[[3]]
#[1] 14 5