R break up data frame into list using vector of number of rows - r

I have a data.frame that I want to break up into a list of data.frames using a vector that will tell me how many rows should be in each consecutive list element.
Sample Data
vectornom <- c(1,2,4,3)
df <- data.frame(x=1:10,y=11:20)
Desired result
> new_list
[[1]]
x y
1 11
[[2]]
x y
2 12
3 13
[[3]]
x y
4 14
5 15
6 16
7 17
[[4]]
x y
8 18
9 19
10 20
I appreciate your help

You can use the (pretty awesome) split function for this, using vectornom to create the index on which to "split"
split(df, rep(1:length(vectornom), vectornom))

Related

R: Divide columns into various subcolumns at specific chosen points / values

I know this might be simple, however, I searched and couldn't find a clear answer, and as non-experienced user of r, I couldn't develop it myself.
I simply need to divide a column in a list or data frame into several sub-columns (not necessarily of equal lengths) at certain defined points of specific order or value. I'm dealing with large data so, so there must be a fast function to directly divide the column according to the chosesn points.
To make it clear, I need to make something like:
# data frame
df<- data.frame(cbind("l1"=c(1:20),"l2"=c(21:40)))
# sepration points
pts<- c(4, 11, 17)
# dividing into sub columns
gp1<-df$l1[1:pts[1]]
gp2<-df$l1[pts[1]:pts[2]]
gp3<-df$l1[pts[2]:pts[3]]
gp4<-df$l1[pts[3]:20]
# combining
res<- list(gp1, gp2, gp3, gp4)
> res
[[1]]
[1] 1 2 3 4
[[2]]
[1] 4 5 6 7 8 9 10 11
[[3]]
[1] 11 12 13 14 15 16 17
[[4]]
[1] 17 18 19 20
But without defining the separation points one by one, and without reordering the data on a value basis.
Thanks in advance for your help!
We can use Map to create the sequence. Concatenate 1 before the 'pts' and nrow at the end of the 'pts' as two separate vectors, use that to create sequence of index with Map and get the corresponding values of 'l1' column of 'df' based on the sequence
Map(function(i, j) df$l1[i:j], c(1, pts), c(pts, nrow(df)))
#[[1]]
#[1] 1 2 3 4
#[[2]]
#[1] 4 5 6 7 8 9 10 11
#[[3]]
#[1] 11 12 13 14 15 16 17
#[[4]]
#[1] 17 18 19 20

Create all possible combinations from two values for each element in a vector in R [duplicate]

This question already has answers here:
How to generate a matrix of combinations
(3 answers)
Closed 6 years ago.
I have been trying to create vectors where each element can take two different values present in two different vectors.
For example, if there are two vectors a and b, where a is c(6,2,9) and b is c(12,5,15) then the output should be 8 vectors given as follows,
6 2 9
6 2 15
6 5 9
6 5 15
12 2 9
12 2 15
12 5 9
12 5 15
The following piece of code works,
aa1 <- c(6,12)
aa2 <- c(2,5)
aa3 <- c(9,15)
for(a1 in 1:2)
for(a2 in 1:2)
for(a3 in 1:2)
{
v <- c(aa1[a1],aa2[a2],aa3[a3])
print(v)
}
But I was wondering if there was a simpler way to do this instead of writing several for loops which will also increase linearly with the number of elements the final vector will have.
expand.grid is a function that makes all combinations of whatever vectors you pass it, but in this case you need to rearrange your vectors so you have a pair of first elements, second elements, and third elements so the ultimate call is:
expand.grid(c(6, 12), c(2, 5), c(9, 15))
A quick way to rearrange the vectors in base R is Map, the multivariate version of lapply, with c() as the function:
a <- c(6, 2, 9)
b <- c(12, 5, 15)
Map(c, a, b)
## [[1]]
## [1] 6 12
##
## [[2]]
## [1] 2 5
##
## [[3]]
## [1] 9 15
Conveniently expand.grid is happy with either individual vectors or a list of vectors, so we can just call:
expand.grid(Map(c, a, b))
## Var1 Var2 Var3
## 1 6 2 9
## 2 12 2 9
## 3 6 5 9
## 4 12 5 9
## 5 6 2 15
## 6 12 2 15
## 7 6 5 15
## 8 12 5 15
If Map is confusing you, if you put a and b in a list, purrr::transpose will do the same thing, flipping from a list of two elements of length three to a list of three elements of length two:
library(purrr)
list(a, b) %>% transpose() %>% expand.grid()
and return the same thing.
I think what you're looking for is expand.grid.
a <- c(6,2,9)
b <- c(12,5,15)
expand.grid(a,b)
Var1 Var2
1 6 12
2 2 12
3 9 12
4 6 5
5 2 5
6 9 5
7 6 15
8 2 15
9 9 15

How can I add vector elements to corresponding vectors in lists?

I have a vectors of variable length in lists and a vector, somewhat like this:
set.seed(0)
x <- lapply(as.list(sample(1:10, 10, repl=TRUE)),
function(x) sample(1:10, x, repl=TRUE))
y <- sample(1:10, 10, repl=TRUE)
I need to add each element of y to a corresponding vector in x. Currently I accomplish this as so:
newList <- list()
for (i in seq_along(y)) {
newList <- c(newList, list(y[i] + x[[i]]))
}
> x[1:2]
[[1]]
[1] 1 3 2 7 4 8 5 8 10
[[2]]
[1] 4 8 10
> y[1:2]
[1] 4 8
> newList
[[1]]
[1] 5 7 6 11 8 12 9 12 14
[[2]]
[1] 12 16 18
[[3]]
[1] 13 17 12 13
...
Is there a better way, perhaps using a lapply-like function?
This is very similar to previous questions, which use Map or mapply to operate on two lists/vectors of the same length in tandem:
How do I apply an index vector over a list of vectors?
Add respective dataframes in list together in R
For this specific case, try:
Map("+",x,y)
#[[1]]
#[1] 5 7 6 11 8 12 9 12 14
#
#[[2]]
#[1] 12 16 18
#
#[[3]]
#[1] 13 17 12 13

How to store the result of a loop over combinatoric pairs of a list?

I have a matrix (but for the purposes of the example I will simplify to a vector).
I want to loop over all pairs of the list. So if the list is length n (or the matrix has n columns), the resulting list has to be (n choose 2) items long.
Suppose n = 6 for the example, but in reality is 36.
Basically, I want a loop like this:
list=1:6
endlist= vector("list", 15) # 15 from 6!/((4!)(2!))
Here is what I want:
Note the below loop does NOT work since there is no i index, and there appears to be no linear combination of j and k that fits the index. Is there a nonlinear one? Or is there a better way to program this?
for(j in 1:5){
for(k in (j+1):6){
endlist[[i]]=list[j]*list[k]
}
}
Giving the output:
endlist=
[[1]]
[1] 2 3 4 5 6
[[2]]
[1] 6 8 10 12
etc.
There's definitely a better way to code that. I'm not sure how this will necessarily apply to your matrix, but for your example:
combn(list, 2, prod)
#[1] 2 3 4 5 6 6 8 10 12 12 15 18 20 24 30
combn() produces combinations of a vector, and can apply a function to each combination(prod). If you really want the output as a list, you can do it with split():
split(combn(list, 2, prod), rep(1:(max(list)-1), times =(max(list)-1):1))
# $`1`
# [1] 2 3 4 5 6
#
# $`2`
# [1] 6 8 10 12
#
# $`3`
# [1] 12 15 18
#
# $`4`
# [1] 20 24
#
# $`5`
# [1] 30
I think the takeaway here is that it's better to calculate your combinations, and work on those, rather than create the combinations yourself in some kind of loop.

Making a data frame that is a subset of two data frames

I am stumped again.
I have two data frames
dataframe1
a b c
[1] 21 12 22
[2] 11 9 6
[3] 4 6 7
and
dataframe2
f g h
[1] 21 12 22
[2] 11 9 6
[3] 4 6 7
I want to take the first column of dataframe1 and make three new dataframes with the second column being each of the three f,g and h
Obviously I could just do a subset over and over
subset1 <- cbind(dataframe1[,1]dataframe2[,1])
subset2 <- cbind(dataframe1[,1]dataframe2[,2])
but my dataframes will have variable numbers of columns and are very long row numberwise. So I am looking for a little more something general. My data frames will always be the same length.
The closest I have come to getting anything was with apply and cbind but I got either a set of three rows that were a and f, a and g, a and h each combined as single numeric vector or I get a single data frame with four columns, a,f,g,h.
Help is deeply appreciated.
You can use lapply it iterate over the columns of dataframe2 like so:
lapply(dataframe2, function(x) as.data.frame(cbind(dataframe1[,1], x)))
This will result in a list object where each entry corresponds to a column of dataframe2. For example:
$f
V1 x
1 21 21
2 11 11
3 4 4
$g
V1 x
1 21 12
2 11 9
3 4 6
$h
V1 x
1 21 22
2 11 6
3 4 7

Resources