Extract vectors from elements of list of vectors - r

I have some json data [{a:10, b:123,c:4.5},{a:2,b:5,c:33}] and so on that I read into R via json_data <- fromJSON(paste(json_file, collapse="")) (json_file is the input url). So far so fine.
Now I would like to create vectors from this input which fromJSON has converted into a List of vectors where the vectors have components a,b,c.
Is there a better way than looping over the input list and doing this manually by concatenating the individual vector components on the new target vector(s)?

If you have a list like this:
l <- list(c(a=10, b=123, c=4.5),c(a=2,b=5,c=33))
You could just do something like the following:
df <- data.frame(do.call(rbind, l))
# a b c
# 1 10 123 4.5
# 2 2 5 33.0
as.list(df)
# $a
# [1] 10 2
# $b
# [1] 123 5
# $c
# [1] 4.5 33.0
(The do.call(rbind, X) construct is handy, allowing you to rbind together the elements of a list of arbitrary length. You can then slice and dice the resulting matrix as you see fit --- I just converted it to a data.frame and then to a list to show a couple of possibilities.)

Related

How can I modify a vector inside a list?

I have a list containing three vectors, say:
test <- list(c(1,2,3,4),c(5,6,7),c(8,9,10))
I'd like to add elements to a given vector in the list. Let's say I'd like to add 11 to the last one (offset 3), so I'd have c(8,9,10,11) as the last element of the "test" list.
I tried:
test[3] <- c(test[3], 11)
test[[3]] <- c(test[1], 11)
test[3[length(test[3])] <- 11
append(test[3], 11)
And apparently nothing of the above works as I expect it to.
How can I do this?
Extract one item with [[
The double square brackets are used to extract one element from potentially many. For vectors yield vectors with a single value; data frames give a column vector; for list, one element text from here
after this use c() to concatenate:
test[[3]] <- c(test[[3]],11)
test[[3]]
[[1]]
[1] 1 2 3 4
[[2]]
[1] 5 6 7
[[3]]
[1] 8 9 10 11
A purrr option (corrected by Ritchie's comment):
test |> purrr::map_at(3, ~ c(.x, 11))

Is R's list() function actually creating a nested list?

R may have its own loigc but list() did not give me what I expected.
l1 <- list(1,2)
$> l1
[[1]]
[1] 1
[[2]]
[1] 2
To retrieve the element, I need to use double-bracket, i.e.,
$> l1[[1]]
[1] 1
$> class(l1[[1]])
"numeric"
Single-bracket gives me, a sub-list (which is also a list object):
$> l1[1]
l1[[1]]
[1] 1
$> class(l1[1])
"list"
I am not saying this is wrong; this isn't what I expected because I was trying to create a 1-dimensional list whereas what I actually get is a nested list, a 2-dimensional object.
What is the logic behind this behaviour and how do we create an OO type list? i.e., a 1-dimensional data structure?
The behaviour I am expecting, with a 1 dimensional data structure, is:
$> l1[1]
[1] 1
$> l1[2]
[2] 2
If you want to create a list with the two numbers in one element, you are looking for this:
l1 <- list(c(1, 2))
l1
#> [[1]]
#> [1] 1 2
Your code basically puts two vectors of length 1 into a list. To make R understand that you have one vector, you need to combine (i.e., c()) the values into a vector first.
This probably becomes clearer when we create the two vectors as objects first:
v1 <- 1
v2 <- 2
l2 <- list(v1, v2)
l2
#> [[1]]
#> [1] 1
#>
#> [[2]]
#> [1] 2
If you simply want to store the two values in an object, you want a vector:
l1 <- c(1, 2)
l1
#> [1] 1 2
For more on the different data structures in R I recommend this chapter: http://adv-r.had.co.nz/Data-structures.html
For the question about [ and [[ indexing, have a look at this classic answer: https://stackoverflow.com/a/1169495/5028841

Subset list of vectors with vector of positions

I have a list of vectors (mylist):
a <- c(1,2,3,4)
b <- c(5,6,7,8)
c <- c(9,10,11,12)
mylist <- list(a,b,c)
I also have a vector of positions (mypos):
mypos <- c(1,2,3)
I would like to use mypos to give the position of elements to subset each vector of mypos so that it returns:
[1] 1 6 11
I have tried using lapply like this:
lapply(mylist, "[", mypos)
but this returns elements 1, 2 and 3 of each vector:
[[1]]
[1] 1 2 3
[[2]]
[1] 5 6 7
[[3]]
[1] 9 10 11
I have also tried:
lapply(mylist, subset, mypos)
But this returns an error that the subset must be logical
We can use Map to extract the corresponding elements of 'mylist' from the index of 'mypos'
Map(`[`, mylist, mypos)
In the OP's code, the 'mypos' is repeated in each of list elements resulting in extracting all the elements from the index. Instead it could be looped on sequence
lapply(seq_along(mylist), function(x) mylist[[x]][mypos[[x]]])

r: how to partition a list or vector into pairs at an offset of 1

sorry for the elementary question but I need to partition a list of numbers at an offset of 1.
e.g.,
i have a list like:
c(194187, 193668, 192892, 192802 ..)
and need a list of lists like:
c(c(194187, 193668), c(193668, 192892), c(192892, 192802)...)
where the last element of list n is the first of list n+1. there must be a way to do this with
split()
but I can't figure it out
in mathematica, the command i need is Partition[list,2,1]
You can try like this, using zoo library
library(zoo)
x <- 1:10 # Vector of 10 numbers
m <- rollapply(data = x, 2, by=1, c) # Creates a Matrix of rows = n-1, each row as a List
l <- split(m, row(m)) #splitting the matrix into individual list
Output:
> l
$`1`
[1] 1 2
$`2`
[1] 2 3
$`3`
[1] 3 4
Here is an option using base R to create a vector of elements
v1 <- rbind(x[-length(x)], x[-1])
c(v1)
#[1] 194187 193668 193668 192892 192892 192802
If we need a list
split(v1, col(v1))
data
x <- c(194187, 193668, 192892, 192802);

Apply function to corresponding elements in list of data frames

I have a list of data frames in R. All of the data frames in the list are of the same size. However, the elements may be of different types. For example,
I would like to apply a function to corresponding elements of data frame. For example, I want to use the paste function to produce a data frame such as
"1a" "2b" "3c"
"4d" "5e" "6f"
Is there a straightforward way to do this in R. I know it is possible to use the Reduce function to apply a function on corresponding elements of dataframes within lists. But using the Reduce function in this case does not seem to have the desired effect.
Reduce(paste,l)
Produces:
"c(1, 4) c(\"a\", \"d\")" "c(2, 5) c(\"b\", \"e\")" "c(3, 6) c(\"c\", \"f\")"
Wondering if I can do this without writing messy for loops. Any help is appreciated!
Instead of Reduce, use Map.
# not quite the same as your data
l <- list(data.frame(matrix(1:6,ncol=3)),
data.frame(matrix(letters[1:6],ncol=3), stringsAsFactors=FALSE))
# this returns a list
LL <- do.call(Map, c(list(f=paste0),l))
#
as.data.frame(LL)
# X1 X2 X3
# 1 1a 3c 5e
# 2 2b 4d 6f
To explain #mnel's excellent answer a bit more, consider the simple example of summing the corresponding elements of two vectors:
Map(sum,1:3,4:6)
[[1]]
[1] 5 # sum(1,4)
[[2]]
[1] 7 # sum(2,5)
[[3]]
[1] 9 # sum(3,6)
Map(sum,list(1:3,4:6))
[[1]]
[1] 6 # sum(1:3)
[[2]]
[1] 15 # sum(4:6)
Why the second one is the case might be made more obvious by adding a second list, like:
Map(sum,list(1:3,4:6),list(0,0))
[[1]]
[1] 6 # sum(1:3,0)
[[2]]
[1] 15 # sum(4:6,0)
Now, the next is more tricky. As the help page ?do.call states:
‘do.call’ constructs and executes a function call from a name or a
function and a list of arguments to be passed to it.
So, doing:
do.call(Map,c(sum,list(1:3,4:6)))
calls Map with the inputs of the list c(sum,list(1:3,4:6)), which looks like:
[[1]] # first argument to Map
function (..., na.rm = FALSE) .Primitive("sum") # the 'sum' function
[[2]] # second argument to Map
[1] 1 2 3
[[3]] # third argument to Map
[1] 4 5 6
...and which is therefore equivalent to:
Map(sum, 1:3, 4:6)
Looks familiar! It is equivalent to the first example at the top of this answer.

Resources