Reputation: 636
Suppose I have a list of indices and values.
indx_list <- list(1,2,c(3,4),5,c(6,7,8))
val_list <- list(0.1,0.6,c(0.8,0.9),0.3,c(0.4,0.8,0.5))
I then want to update both lists by removing indices c(4,7)
and the corresponding values c(0.9,0.5)
. This is pretty easily done using lapply
and setdiff
. For example:
indx_list_new <- lapply(indx_list,function(x) setdiff(x,c(4,7)))
val_list_new <- lapply(val_list,function(x) setdiff(x,c(0.9,0.5)))
However, I don't know beforehand what indices and corresponding values I will be removing.
set.seed(1234)
indx_flag <- sample(seq(8),2)
You can also see that some values are repeated (i.e. 0.8) so using setdiff
might actually remove values at the wrong position.
1) I can still use lapply
and setdiff
to update indx_list
, but how can I update the values in val_list
?
2) Is lapply
the most efficient solution here? I will have lists with thousands of elements, and each element can be a vector of hundreds of indices/values.
Each element in the list (highest level) actually has a particular meaning, so I'd like to keep the list structure.
Upvotes: 2
Views: 401
Reputation: 46856
Instead, arrange your data into a 'tidy' representation
df = data.frame(
indx = unlist(indx_list),
val = unlist(val_list),
grp = factor(rep(seq_along(indx_list), lengths(indx_list)))
)
where the operation is more-or-less transparent
base::subset(df, !indx %in% c(4, 7))
indx val grp
1 1 0.1 1
2 2 0.6 2
3 3 0.8 3
5 5 0.3 4
6 6 0.4 5
8 8 0.5 5
Using subset()
is similar to df[!df$indx %in% c(4, 7), , drop = FALSE]
. (I used factor()
to allow for empty groups, i.e., levels with no corresponding values).
Upvotes: 2
Reputation: 93813
Here's an attempt using relist
and Map
to remove the same points:
Map(`[`, val_list, relist(!unlist(indx_list) %in% c(4,7), indx_list))
#[[1]]
#[1] 0.1
#
#[[2]]
#[1] 0.6
#
#[[3]]
#[1] 0.8
#
#[[4]]
#[1] 0.3
#
#[[5]]
#[1] 0.4 0.5
Upvotes: 1