I want to run a function on each level of a data.frame variable based on the condition of each level of another data.frame variable (or lists, if it's better to work with them for some reason).
If one of the variables achieves a certain condition (eg, > 15), I then want to run a simple function (eg, product) on each pair of variables and add the results to a new list. For the sake of my needs and other's future needs, I am hoping for a solution that is flexible for any condition and any function.
I am new to programming/R and do not know how to appropriate structure a for loop (or other method) in order to run the function for all combinations of elements in both data.frame variables. It seems like this should be really easy to achieve but I've been searching for hours and cannot find a solution.
This is the nested for loop code I am working on:
df1 <- data.frame(c(1, 2, 3))
df2 <- data.frame(c(10, 20, 30))
list1 <- list()
for (i in 1:length(df1)) {
for (j in 1:length(df2)) {
if (df2[j,] > 15) {
list1[[i]] <- df1[i,] * df2[j,]}
}}
list1
When I run the current code I get and empty list results: list(). What I want returned is something like this:
[[1]]
[1] 20
[[2]]
[1] 30
[[3]]
[1] 40
[[4]]
[1] 60
[[5]]
[1] 60
[[6]]
[1] 90
Consider sapply
with two inputs to iterate across nrow
of both data frames with list conversion:
mat <- sapply(1:nrow(df2), function(i, j) ifelse(df2[j,] > 15, df1[i,]*df2[j,], NA),
1:nrow(df1))
mat <- mat[!is.na(mat)]
mat
# [1] 20 30 40 60 60 90
as.list(mat)
# [[1]]
# [1] 20
#
# [[2]]
# [1] 30
#
# [[3]]
# [1] 40
#
# [[4]]
# [1] 60
#
# [[5]]
# [1] 60
#
# [[6]]
# [1] 90
There are many ways to do this, here are two of them: one is your for
loop and another is vectorised.
for
loop
There are few mistakes in your code, both df1
and df2
have length
= 1. Therefore, i
and j
are only set as 1. This can be fixed by using nrow
instead of length
. Another thing is to create an index
outside the loop to assign your results to list. Following code works
df1 <- data.frame(c(1, 2, 3))
df2 <- data.frame(c(10, 20, 30))
list1 <- list()
index=0
for (i in 1:nrow(df1)) {
for (j in 1:nrow(df2)) {
if (df2[j,] > 15) {
index=index+1
list1[[index]] <- df1[i,] * df2[j,]}
}}
list1
[[1]]
[1] 20
[[2]]
[1] 30
[[3]]
[1] 40
[[4]]
[1] 60
[[5]]
[1] 60
[[6]]
[1] 90
vectorized way
Using expand.grid
to generate the required combinations and prod
to find their products
dat=expand.grid(df1[,1], df2[df2 > 15,1])
dat=dat[order(dat$Var1),]
apply(dat, 1, prod)
1 4 2 5 3 6
20 30 40 60 60 90
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.