rexpand

R Expand Data Frame List


DATA = data.frame(STUDENT = c(1:3),
                  G1 = c(2,2,1),
                  G2 = c(3,5,4))

DATA1 = data.frame(STUDENT1 = c(0,1,1,0,0),
                   STUDENT2 = c(0,1,1,1,1),
                   STUDENT3 = c(1,1,1,1,0))

For each STUDENT in DATA I wish to create a new column that has 5 rows, Imagine filling all the rows with 0 but then filling in the row with a value of '1' if the row number is within the range between G1 and G2 from DATA for every student, like show in DATA1


Solution

  • dplyr+tidyr

    library(dplyr
    library(tidyr) # pivot_wider
    DATA |>
      rowwise() |>
      reframe(STUDENT, row = 1:5, val = replace(rep(0, 5), G1:G2, 1)) |>
      pivot_wider(id_cols = row, names_from = STUDENT, values_from = val, names_prefix = "STUDENT") |>
      select(-row)
    

    data.table

    library(data.table)
    out <- as.data.table(DATA)[, .(STUDENT, row = 1:5, val = replace(rep(0, 5), G1:G2, 1)),
                               by = 1:nrow(DATA) ] |>
      dcast(row ~ STUDENT, value.var="val") |>
      _[, row := NULL] # needs R-4.3 or newer for the `|> _[]` trick
    setnames(out, paste0("STUDENT", names(out)))
    out
    #    STUDENT1 STUDENT2 STUDENT3
    #       <num>    <num>    <num>
    # 1:        0        0        1
    # 2:        1        1        1
    # 3:        1        1        1
    # 4:        0        1        1
    # 5:        0        1        0