I'd like to change a list into one cell of a data frame.
list <- list(1,2,3,4,5)
View(list)
[[1]]
[1] 1
[[2]]
[1] 2
[[3]]
[1] 3
[[4]]
[1] 4
[[5]]
[1] 5
I'd like to transform this such that it looks like:
x
1 1,2,3,4,5
The reason is because I have a loop that is storing result in a list for each iteration, but I only want one cell per iteration.
There are other columns where for each iteration, there is only one result. So saving that in a data frame is easy. But then for the metric with multiple results, I don't want multiple columns or rows.
So I will have two data frames that I can use cbind on such that my final data frame will look like:
x y
1 1,2,3,4,5 a
2 5,4,3 b
You can easily achieve that by unlist and paste, i.e.,
data.frame(x = paste(l1, collapse = ','))
# x
#1 1,2,3,4,5
or simply (thanks #David)
data.frame(x = toString(list))
# x
#1 1, 2, 3, 4, 5
On a side note, avoid naming your lists 'list' as there is a function called list in R
Related
Suppose I have a list of length 2, within which is another list of length 2, within which there is a data frame of numbers coded as either 0, 1 or 2 (bear with me!):
set.seed(42)
l1<-data.frame(sample(0:2, 5, replace = TRUE))
l2<-data.frame(sample(0:2, 5, replace = TRUE))
l<-list(l1,l2)
ll<-list(list(l,l), list(l,l))
I need to count the number of times either 1 or 2 appears within each data frame. I then need to sum these counts across all counts at the level above.
So for ll[[1]][[1]][[1]] the count would be 1, for ll[[1]][[1]][[2]] the count would be 4. Across those two dataframes the sum would be 5.
To give a more plain-English description of the real data I'm working with: the top level is the number of species (in this example, 2 species), the level below that is the year when data was recorded (in this example, data is collected in 2 different years). Below that is a location within which data are recorded. I need to know that, within years, how many times 1 or 2 appears across all locations (within that year).
There is perhaps a better way to describe this but so far it's eluding me. Any help would be appreciated.
We can use purrr functions.
library(purrr)
map(ll, function(x) transpose(x) %>% map(~sum(unlist(.x) != 0)))
#[[1]]
#[[1]][[1]]
#[1] 2
#[[1]][[2]]
#[1] 8
#[[2]]
#[[2]][[1]]
#[1] 2
#[[2]][[2]]
#[1] 8
A bit nested, but the solution should work:
lapply(ll,
function(l)
lapply(l,
function(li) sum(unlist(li) %in% 1:2)))
# [[1]]
# [[1]][[1]]
# [1] 5
#
# [[1]][[2]]
# [1] 5
#
#
# [[2]]
# [[2]][[1]]
# [1] 5
#
# [[2]][[2]]
# [1] 5
I have data consisting of many columns/variables and three rows. Each variable is an integer and the values vary across rows and columns. Below is a minimal example of my data:
# Minimal example of data frame I have
df <- data.frame(x1 = c(1,2,3),
x2 = c(4,1,6),
x3 = c(3,0,2),
x4 = c(3,0,1))
I am trying to somehow collapse each column into a numeric vector containing the values in each row. For example, I want something like:
# Desired data based on minimal example
target_list <- list(c(1,2,3),
c(4,1,6),
c(3,0,2),
c(3,0,1))
The ultimate goal is to be able to take another data frame with many columns and generate a new data frame containing only the columns with indices matching the values in each numeric vector. For each vector, I generate another data frame. All frames are stored in a list. An example of my target output given the working example inputs:
# Example "super data frame" I will subset. The values contained in each column are arbitrary.
df2 <- data.frame(z1 = "a", z2 = "b",
z3 = 999, z4 = NA,
z5 = "foo", z6 = "bar")
# Subset "super data frame" to only columns in each vector in the list, store in a list
list(df2[ ,target_list[[1]]],
df2[ ,target_list[[2]]],
df2[ ,target_list[[3]]],
df2[ ,target_list[[4]]])
I've tried various pasting approaches, but they produce character vectors that I can't use to select the columns of the other data frame by index, e.g. it produces this:
paste0(df[1, ], df[2, ], df[3, ], df[4, ])
Any help on how to generate the list of numeric vectors from df?
Or use as.list
as.list(df)
#$x1
#[1] 1 2 3
#$x2
#[1] 4 1 6
#$x3
#[1] 3 0 2
#$x4
#[1] 3 0 1
You can use unname to remove names of the list.
Maybe I'm missing something, but the only difference between your input and your target are three attributes:
attributes(df)
#$names
#[1] "x1" "x2" "x3" "x4"
#
#$class
#[1] "data.frame"
#
#$row.names
#[1] 1 2 3
You can remove them:
attributes(df) <- NULL
df
#[[1]]
#[1] 1 2 3
#
#[[2]]
#[1] 4 1 6
#
#[[3]]
#[1] 3 0 2
#
#[[4]]
#[1] 3 0 1
Or, alternatively:
c(unname(unclass(df)))
But, of course, these attributes don't hurt and you can always treat a data.frame like a list (because it actually is a list).
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);
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.
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.)