Reputation: 43
the dataset marks
X <- c("vijay","raj","joy")
Y <- c("maths","eng","science","social","hindi","physical","sanskrit")
df <- list()
for (i in X){
for (j in Y)
{
df <- data.frame(subset(marks, name == i & subject == j))
}
}
here I want to create subsets having marks of all subject against each student. Thus we want to have 3 X 7 subsets. But the code I wrote is giving me single subset. How can solve the problem?
Upvotes: 2
Views: 94
Reputation: 12559
You can use outer()
but you have to vectorize the inner function:
X <- c("vijay","raj","joy")
Y <- c("maths","eng","science","social","hindi","physical","sanskrit")
set.seed(24)
marks <- data.frame(name = sample(X, 100, replace = TRUE),
subject = sample(Y, 100, replace = TRUE), stringsAsFactors = FALSE)
sset <- function(x,y) subset(marks, name == x & subject == y)
L <- outer(X, Y, FUN=Vectorize(sset, SIMPLIFY=FALSE))
L[1,1]
The object L
is a matrix of dataframes.
Here is another solution using a double lapply()
:
L2 <- lapply(X, function(x) lapply(Y, function(y) subset(marks, name == x & subject == y)))
The object L2
is a list of lists.
Here is a variant with for-loops:
df <- vector("list", length(X)*length(Y))
l <- 1
for (i in X) for (j in Y) {
df[[l]] <- subset(marks, name == i & subject == j)
l <- l+1
}
For subsetting only for existing levels you can simply use split()
L3 <- split(marks, list(marks$name, marks$subject))
The objekt L3
is a list of dataframes.
Upvotes: 3
Reputation: 887118
We could do this with expand.grid
to create all the combinations, then loop through the rows of the dataset and subset
the 'marks' to get a list
of data.frame
s
dat <- expand.grid(X, Y, stringsAsFactors = FALSE)
lst <- apply(dat, 1, function(x) subset(marks, name == x[1] & subject == x[2]))
Or using tidyverse
library(tidyverse)
crossing(X, Y) %>%
pmap(~ marks %>%
filter(name == ..1, subject == ..2))
set.seed(24)
marks <- data.frame(name = sample(X, 100, replace = TRUE),
subject = sample(Y, 100, replace = TRUE), stringsAsFactors = FALSE)
Upvotes: 3