'How to copy data from a dataframe to a matrix horizontally as per the defined date and extent?

I want to achieve mentioned output for the below input.

Input:

Extent Date Sun Mon Tue Wed Thu Fri Sat
2 10-Mar-22 a b c d e f g
8 08-Mar-22 A B C D E F G

Code snippet for input:

input_df <- structure(list(extent = c(2,8), Date = c("10-Mar-22","08-Mar-22"),Sun = c("a", "A"), Mon = c("b", "B"), Tue = c("c", "C"), Wed = c("d", "D"), Thu = c("e", "E"), Fri = c("f", "F"), Sat = c("g", "G")), row.names = c(NA, -2L), class = "data.frame")

Rules to achieve the output:

  1. The maximum of extent defines the no. of columns in output
  2. Rows of input = Rows of output
  3. Day of the week of the Date in input indicates the starting point to copy the data into output
  4. Extent tells how many cells to copy
  5. Once data copying reaches Sat, it should start back from Sun until the Extent is satisfied

Output:

1 2 3 4 5 6 7 8
e f
C D E F G A B C

Please help me with a solution which uses vector operation.



Solution 1:[1]

That's a very unusual data transformation, and there's no simple way to do it. But this might suit your needs. Note that the output rows are ordered by "Date", and therefore are in a different order than your example.

library(tidyverse)
library(lubridate)

df_split <- split(input_df, input_df$Date)
output_df <- lapply(df_split, function(x) {
  
  vals <- unlist(x[-1:-2])
  date_weekday <- wday(dmy(x$Date))
  span <- date_weekday:(date_weekday + x$extent - 1)
  span <- ((span - 1) %% 7) + 1
  reorder <- unname(vals[span])
  cols <- as.data.frame(t(reorder))
  return(cols)
  
})

output_df <- do.call(bind_rows, output_df)

output_df

  V1 V2   V3   V4   V5   V6   V7   V8
1  C  D    E    F    G    A    B    C
2  e  f <NA> <NA> <NA> <NA> <NA> <NA>

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1