Operations between elements in the corresponding position of the data frame

Hi,
As the R beginner, I met a practice that make me confused.

I want to know if the elment in the same position in three dataframe(d1,d2,d3) has the relationship d1<d3<d2. if yes, we add the element,d1+d2. if no, we substract,d1-d2. And write the result in same position in d4.

For example, when rownumber=2,column number=1, this element in d3=3.4. 3(same position in d1) <3.4<4.0(same position in d2). So in d4(2nd row, 1st colnumn), we write 3+4=7.

While, I just complete 1 column. I don't know how to complete the rest. Maybe based on loop function or else? Hope that not combine the d1,d2,d3 into a new dataframe, and think when there are many columns(>3).

Thank you for help in advance.

d1<-data.frame(c1<-c(2,3,4),
               c2<-c(3,8,6),
               c3<-c(1,9,6))
colnames(d1)<-c("c1","c2","c3")

d2<-data.frame(c4<-c(1,4,5),
               c5<-c(2,5.5,7),
               c6<-c(3.1,6.3,2))
colnames(d2)<-c("c4","c5","c6")

d3<-data.frame(c7<-c(0.1,3.4,3),
               c8<-c(3,8,6.9),
               c9<-c(2.8,6.9,6))
colnames(d3)<-c("c7","c8","c9")

d4<-data.frame(matrix(nrow=3,ncol=3))

for(i in 1:nrow(d1)){
  if(d3[i,1]<d2[i,1] & d3[i,1]>d1[i,1]){
    d4[i,1]<-d1[i,1]+d2[i,1]
  } else{
    d4[i,1]<-d1[i,1]-d2[i,1]
  }
}

Created on 2022-11-19 with reprex v2.0.2
image

Here is a solution with no loops.

d1<-data.frame(c1<-c(2,3,4),
               c2<-c(3,8,6),
               c3<-c(1,9,6))
colnames(d1)<-c("c1","c2","c3")

d2<-data.frame(c4<-c(1,4,5),
               c5<-c(2,5.5,7),
               c6<-c(3.1,6.3,2))
colnames(d2)<-c("c4","c5","c6")

d3<-data.frame(c7<-c(0.1,3.4,3),
               c8<-c(3,8,6.9),
               c9<-c(2.8,6.9,6))
colnames(d3)<-c("c7","c8","c9")
Comp1 <- d1 < d3 
Comp2 <- d3 < d2
Comp1
#>         c1    c2    c3
#> [1,] FALSE FALSE  TRUE
#> [2,]  TRUE FALSE FALSE
#> [3,] FALSE  TRUE FALSE
Comp2
#>        c7    c8    c9
#> [1,] TRUE FALSE  TRUE
#> [2,] TRUE FALSE FALSE
#> [3,] TRUE  TRUE FALSE
FinalComp <- Comp1 & Comp2
FinalComp <- as.data.frame(FinalComp)
FinalComp
#>      c1    c2    c3
#> 1 FALSE FALSE  TRUE
#> 2  TRUE FALSE FALSE
#> 3 FALSE  TRUE FALSE
d4 <- data.frame(matrix(nrow=3,ncol=3))
d4 <- mapply(function(v1,v2,v3) ifelse(v3, v1 + v2, v1-v2), d1, d2, FinalComp)
d4
#>      c1   c2  c3
#> [1,]  1  1.0 4.1
#> [2,]  7  2.5 2.7
#> [3,] -1 13.0 4.0

Created on 2022-11-19 with reprex v2.0.2

2 Likes

Thank you for your effort and time in this matter.
Would mind teach me how to use the loop function to solve it? I want to learn more from you. It wolud do me a great favor when i met similar prolem in future.

If you want to iterate over the columns as well as the rows, you need to use another for loop that contains the for loop you already wrote

for(j in ...) {
  for(i in 1:nrow(d1)){
    if(d3[i,1]<d2[i,1] & d3[i,1]>d1[i,1]){
      d4[i,1]<-d1[i,1]+d2[i,1]
    } else{
      d4[i,1]<-d1[i,1]-d2[i,1]
    }
  }
}

and you need to replace all of the 1 values in your data frame indexes, [i, 1], with j. Also, the ... in my examples must be replaced with appropriate code.

My problem has been solved. It works! I am very appreciative of your effort and help on this matter.

@FJCC could you please elaborate a bit what does this code do ? I know lapply, sapply, never used mapply.
Thank you.

The mapply function acts on multiple objects. In this case, it takes data from three data frames. Think of the data frames as lists with each element being a column. mapply() takes the first column of d1, d2, and FinalComp and passes them to the function as the arguments v1, v2, and v3. mapply() then moves on to the second column of each data frame. If the data frames did not have the same number of columns, the columns would be recycled as needed. So, mapply() acts just like sapply() or lapply() except that it works on two or more lists at the same time.

1 Like

Thank you, it was very helpful.

Hi, @FJCC
I met another problem about this. If there are NA, how could i just still to achieve it by loop function? While the NA, is stll NA in d4. Others are not influenced. When rownumber=2,column number=1, this element in d3=3.4. 3(same position in d1) <3.4<4.0(same position in d2). So in d4(2nd row, 1st colnumn), we write 3+4=7. It is still 7. If I just run the code when there is no NA to handle the data with NA, it would have an error. Thank you very much.

d1<-data.frame(c1<-c(2,3,NA),
               c2<-c(3,8,6),
               c3<-c(1,9,6))
colnames(d1)<-c("c1","c2","c3")

d2<-data.frame(c4<-c(1,4,NA),
               c5<-c(2,5.5,7),
               c6<-c(3.1,6.3,2))
colnames(d2)<-c("c4","c5","c6")

d3<-data.frame(c7<-c(0.1,3.4,NA),
               c8<-c(3,8,6.9),
               c9<-c(2.8,6.9,6))
colnames(d3)<-c("c7","c8","c9")
d4<-data.frame(matrix(nrow=3,ncol=3))

for(j in 1:ncol(d1)) {
  for(i in 1:nrow(d1)){
    if(d3[i,j]<d2[i,j] & d3[i,j]>d1[i,j]){
      d4[i,j]<-d1[i,j]+d2[i,j]
    } else{
      d4[i,j]<-d1[i,j]-d2[i,j]
    }
  }
}
#> Error in if (d3[i, j] < d2[i, j] & d3[i, j] > d1[i, j]) {: missing value where TRUE/FALSE needed

Created on 2022-11-22 with reprex v2.0.2

In this version, if any of the elements of d1, d2, or d3 is NA, the loops skips the calculation.

for(j in 1:ncol(d1)) {
  for(i in 1:nrow(d1)){
    if(!any(is.na(c(d3[i,j],d2[i,j],d1[i,j])))) {
      if(d3[i,j]<d2[i,j] & d3[i,j]>d1[i,j]){
        d4[i,j]<-d1[i,j]+d2[i,j]
      } else{
        d4[i,j]<-d1[i,j]-d2[i,j]
      }
    }
  }
}

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.