Indexing table in [R] - r

I have a vector:
a = c(1, 3, 2, 2, 4, 1, 1, NA)
I want to generate something like:
[["1"]]
1, 6, 7
[["2"]]
3, 4
[["3"]]
2
[["5"]]
5
Mapping from value to index. Any help!

This is a split operation on the indexes of a:
split(seq_along(a), a)
#$`1`
#[1] 1 6 7
#
#$`2`
#[1] 3 4
#
#$`3`
#[1] 2
#
#$`4`
#[1] 5

setNames(lapply(unique(a), function(x) which(x == a)), unique(a))
# $`1`
# [1] 1 6 7
#
# $`3`
# [1] 2
#
# $`2`
# [1] 3 4
#
# $`4`
# [1] 5
#
# $<NA>
# integer(0)
This is slightly shorter using tidyverse
library(tidyverse)
map(unique(a) %>% setNames(.,.), ~which(.x == a))

Here is another option with unstack
unstack(list(i = seq_along(a), a), i ~ a)
#$`1`
#[1] 1 6 7
#$`2`
#[1] 3 4
#$`3`
#[1] 2
#$`4`
#[1] 5

Related

R arrange list of vectors

Say I have a list of vectors like this:
list.of.vec <- data.frame(id = c(1,2,3,4)) %>%
mutate(a = list(list(c(1,2,3), c(2,3,4)), list(c(2,4,5), c(1,3,4)), list(c(1,2,3), c(4,3,4)), list(c(3,2,3), c(2,3,4))))
how can I arrange a such that in each pair of vectors, the one with the bigger first values goes first? E.g., if there was a list c(1,2,3), c(2,3,4), it should become c(2,3,4), c(1,2,3). And if first values are equal then it looks at the next value.
We can use rrapply
library(rrapply)
library(purrr)
library(dplyr)
list.of.vec <- list.of.vec %>%
mutate(a = map(a, ~ .x[order(-rrapply(.x, f = function(x) x[1],
how = 'unlist'))]))
-output
> list.of.vec
id a
1 1 2, 3, 4, 1, 2, 3
2 2 2, 4, 5, 1, 3, 4
3 3 4, 3, 4, 1, 2, 3
4 4 3, 2, 3, 2, 3, 4
> list.of.vec$a
[[1]]
[[1]][[1]]
[1] 2 3 4
[[1]][[2]]
[1] 1 2 3
[[2]]
[[2]][[1]]
[1] 2 4 5
[[2]][[2]]
[1] 1 3 4
[[3]]
[[3]][[1]]
[1] 4 3 4
[[3]][[2]]
[1] 1 2 3
[[4]]
[[4]][[1]]
[1] 3 2 3
[[4]][[2]]
[1] 2 3 4
You can use -
list.of.vec$a <- lapply(list.of.vec$a, function(x) {
inds <- match(TRUE, x[[1]] != x[[2]])
if(x[[1]][inds] > x[[2]][inds]) x else rev(x)
})
list.of.vec$a
#[[1]]
#[[1]][[1]]
#[1] 2 3 4
#[[1]][[2]]
#[1] 1 2 3
#[[2]]
#[[2]][[1]]
#[1] 2 4 5
#[[2]][[2]]
#[1] 1 3 4
#[[3]]
#[[3]][[1]]
#[1] 4 3 4
#[[3]][[2]]
#[1] 1 2 3
#[[4]]
#[[4]][[1]]
#[1] 3 2 3
#[[4]][[2]]
#[1] 2 3 4
inds would return the index for each list that we need to compare, an index where the value is different in both the vectors. If the first index has a higher value we return the list as it is without any change or else we return the reversed list.
We can try
lapply(
a,
function(x) {
x[order(-sapply(x, `[`, 1))]
}
)
which gives
[[1]]
[[1]][[1]]
[1] 2 3 4
[[1]][[2]]
[1] 1 2 3
[[2]]
[[2]][[1]]
[1] 2 4 5
[[2]][[2]]
[1] 1 3 4
[[3]]
[[3]][[1]]
[1] 4 3 4
[[3]][[2]]
[1] 1 2 3
[[4]]
[[4]][[1]]
[1] 3 2 3
[[4]][[2]]
[1] 2 3 4

Convert each row of dataframe to new list in R

I have below sample input data-
> df <- data.frame(a=c(1,2,9),b=c(3,4,5),c=c(2,6,7))
> df
a b c
1 1 3 2
2 2 4 6
3 9 5 7
I am trying to convert rach row into separate list.
My Attempt-
> apply(df,1,as.list)
The above solution converts each row into sublists. But, I am looking for 3 separate list in this case.
nrow(df) = no. of lists
Desired Output-
> list1
$a
[1] 1
$b
[1] 3
$c
[1] 2
> list2
$a
[1] 2
$b
[1] 4
$c
[1] 6
> list3
$a
[1] 9
$b
[1] 5
$c
[1] 7
You can use by and as.list
out <- by(df, 1:nrow(df), as.list)
out
#1:nrow(df): 1
#$a
#[1] 1
#
#$b
#[1] 3
#$c
#[1] 2
#------------------------------------------------------------------------------
#1:nrow(df): 2
#$a
#[1] 2
#$b
#[1] 4
#$c
#[1] 6
#------------------------------------------------------------------------------
#1:nrow(df): 3
#$a
#[1] 9
#$b
#[1] 5
#$c
#[1] 7
That creates an object of class by. So you may call unclass(out) in the end.

Split to list() based on condition, omiting the False elements

What is the most elegant way to split a vector into n-Elements based on a condition?
Every separate true-block should go into its own list element. All the false elements get thrown away.
example1:
vec <- c(1:3,NA,NA,NA,4:6,NA,NA,NA,7:9,NA)
cond <- !is.na(vec)
result = list(1:3,4:6,7:9)
example2:
vec_2 <- c(3:1,11:13,6:4,14:16,9:7,20)
cond_2 <- vec_2 < 10
results_2 = list(3:1,6:4,9:7)
It would be great to have a general solution for a vector vec and a relating condition cond.
My best try:
res <- split(vec,data.table::rleidv(cond))
odd <- as.logical(seq_along(res)%%2)
res[if(cond[1])odd else !odd]
I guess this should work generally:
> split(vec[cond], data.table::rleid(cond)[cond])
$`1`
[1] 1 2 3
$`3`
[1] 4 5 6
$`5`
[1] 7 8 9
Let's make it a function:
> f <- function(vec, cond) split(vec[cond], data.table::rleid(cond)[cond])
> f(vec_2, cond_2)
$`1`
[1] 3 2 1
$`3`
[1] 6 5 4
$`5`
[1] 9 8 7
Here is a base R option with rle
grp <- with(rle(cond), rep(seq_along(values) * NA^ !values, lengths))
split(vec[cond], grp[cond])
#$`1`
#[1] 1 2 3
#$`3`
#[1] 4 5 6
#$`5`
#[1] 7 8 9
Similarly with 'vec_2'
grp <- with(rle(cond_2), rep(seq_along(values) * NA^ !values, lengths))
split(vec_2[cond_2], grp[cond_2])
#$`1`
#[1] 3 2 1
#$`3`
#[1] 6 5 4
#$`5`
#[1] 9 8 7
Or create a grouping variable with cumsum and diff
grp <- cumsum(c(TRUE, diff(cond) < 0)) * NA^ is.na(vec)

How to delete specific elements in a list

I have a list:
aa <- list(c(12, 1, 5, 4), c(2, 3, 5), c(6, 4,1))
aa
#[[1]]
#[1] 12 1 5 4
#[[2]]
#[1] 2 3 5
#[[3]]
#[1] 6 4 1
I would like to delete all "4" and "5" in aa and be able to return the following list:
#[[1]]
#[1] 12 1
#[[2]]
#[1] 2 3
#[[3]]
#[1] 6 1
So is there a simple way of doing this? Thank you.
Here you have a simple solution using lapply:
lapply(aa, function(x) {x[!(x %in% c(4, 5))]})
Output:
[[1]]
[1] 12 1
[[2]]
[1] 2 3
[[3]]
[1] 6 1

Reverse sort list by max element

I have a list of vectors
l = list(c(1,2),c(3,4),c(2,3),c(7,8),c(5,6))
and would to reverse sort it by the vector maximums:
> l
[[1]]
[1] 7 8
[[2]]
[1] 5 6
[[3]]
[1] 3 4
[[4]]
[1] 2 3
[[5]]
[1] 1 2
Any idea how I could do this in a one liner? thx
One way is
l[order(sapply(l, max), decreasing=TRUE)]
#[[1]]
#[1] 7 8
#[[2]]
#[1] 5 6
#[[3]]
#[1] 3 4
#[[4]]
#[1] 2 3
#[[5]]
#[1] 1 2
You could replace sapply(l, max) with vapply(l, max, numeric(1L)) as well.
Or a compact form suggested by #DavidArenburg
l[order(-sapply(l, max))]

Resources