Introducing data in a dataframe by criterion

Viewed 57

Let's suppose I have the following data frame:

df <- data.frame(A=c(0),
                 B=c(0), 
                 C=c(0), 
                 D=c(0),
                 E=c(0)) 

Now, I want to introduce in df some vectors like these ones, introducing 0 when a parameter which is contemplated in df but not in the vectors is missing.

Ex1 <- data.frame(B=c(1), 
                  C=c(2), 
                  D=c(4))

Ex2 <- data.frame(A=c(1), 
                  E=c(6))

That means, the result should look like this:

A B C D E
0 0 0 0 0
0 1 2 4 0
1 0 0 0 6
3 Answers

We can use bind_rows from dplyr which will automatically fill with NA when missing, then replace the NA to 0 later

library(dplyr)
library(tidyr)
bind_rows(df, Ex1, Ex2) %>%
    mutate(across(everything(), replace_na, 0))

-output

  A B C D E
1 0 0 0 0 0
2 0 1 2 4 0
3 1 0 0 0 6

We could also do this in base R with row/column indexing i.e. create a matrix of 0 values and then fill each row with the row index and the column names from the "Ex1", "Ex2" data

m1 <- matrix(0, nrow = 3, ncol = 5, dimnames = list(NULL, LETTERS[1:5]))
m1[2, names(Ex1)] <- as.matrix(Ex1)
m1[3, names(Ex2)] <- as.matrix(Ex2)
 m1
     A B C D E
[1,] 0 0 0 0 0
[2,] 0 1 2 4 0
[3,] 1 0 0 0 6

You can try the code bekow

library(data.table)
library(dplyr)

list(df, Ex1, Ex2) %>%
  rbindlist(fill = TRUE) %>%
  replace(is.na(.), 0)

which gives

   A B C D E
1: 0 0 0 0 0
2: 0 1 2 4 0
3: 1 0 0 0 6

You could try a small loop.

for (i in seq.int(L)) {
  df[i + 1, ] <- 0
  z <- colSums(df) == 0 & names(df) %in% names(L[[i]])
  df[i + 1, z] <- L[[i]]
  }
df
#   A B C D E
# 1 0 0 0 0 0
# 2 0 1 2 4 0
# 3 1 0 0 0 6

Data:

df <- structure(list(A = 0, B = 0, C = 0, D = 0, E = 0), row.names = 1L, class = "data.frame")

ex1 <- structure(list(B = 1, C = 2, D = 4), class = "data.frame", row.names = c(NA, 
-1L))

ex2 <- structure(list(B = 1, C = 2, D = 4), class = "data.frame", row.names = c(NA, 
-1L))

L <- list(ex1, ex2)
Related