Search code examples
rdataframemutate

Is there a way to select data in a form of windows sliding?


i want to generate a new data with five columns using a slinding window of 5 from the main dataset.

my desired output resluts:

dataset     
disp1   disp2   disp3
-2.5    -4.8    -1.4
1.3 0.6 3.1
-1.7    -6.4    -1.7
-8.9    9.7 -5.3
-5  -3.1    -1.1
-4.8    -5.7    -0.1
-7.7    -4.4    -3.7
3.4 1.8 15.5
14.2    3.5 7.2
-10.2   5.4 -8.6

desired results:

newdata             
I   II  III IV  Output
-2.5    1.3 -1.7    -8.9    -5
1.3 -1.7    -8.9    -5  -4.8
-1.7    -8.9    -5  -4.8    -7.7
-8.9    -5  -4.8    -7.7    3.4
-5  -4.8    -7.7    3.4 14.2
-4.8    -7.7    3.4 14.2    -10.2
-7.7    3.4 14.2    -10.2   -4.8
3.4 14.2    -10.2   -4.8    0.6
14.2    -10.2   -4.8    0.6 -6.4
-10.2   -4.8    0.6 -6.4    9.7
-4.8    0.6 -6.4    9.7 -3.1
0.6 -6.4    9.7 -3.1    -5.7
-6.4    9.7 -3.1    -5.7    -4.4
9.7 -3.1    -5.7    -4.4    1.8
-3.1    -5.7    -4.4    1.8 3.5
-5.7    -4.4    1.8 3.5 5.4
-4.4    1.8 3.5 5.4 -1.4
1.8 3.5 5.4 -1.4    3.1
3.5 5.4 -1.4    3.1 -1.7
5.4 -1.4    3.1 -1.7    -5.3
-1.4    3.1 -1.7    -5.3    -1.1
3.1 -1.7    -5.3    -1.1    -0.1
-1.7    -5.3    -1.1    -0.1    -3.7
-5.3    -1.1    -0.1    -3.7    15.5
-1.1    -0.1    -3.7    15.5    7.2
-0.1    -3.7    15.5    7.2 -8.6

i tried using mutate and for loop but i was not able to get the desired results


Solution

  • Steps:

    1. Turn the dataframe into a vector.
    2. Select the size we want the resulting matrix to be (in this case, five).
    3. Use vapply(): from the first to the size minus 1-th index, get the next size values from the vector.
    4. Transpose the matrix, because vapply() gives us a wide matrix, when we want a long one.
    v <- unlist(df)
    size <- 5
    vapply(seq_along(v)[1:(length(v)- size + 1)], \(x) vals[x:(x + size - 1)], numeric(size)) |> t()
    

    Output:

          disp11 disp12 disp13 disp14 disp15
     [1,]   -2.5    1.3   -1.7   -8.9   -5.0
     [2,]    1.3   -1.7   -8.9   -5.0   -4.8
     [3,]   -1.7   -8.9   -5.0   -4.8   -7.7
     [4,]   -8.9   -5.0   -4.8   -7.7    3.4
     [5,]   -5.0   -4.8   -7.7    3.4   14.2
     [6,]   -4.8   -7.7    3.4   14.2  -10.2
     [7,]   -7.7    3.4   14.2  -10.2   -4.8
     [8,]    3.4   14.2  -10.2   -4.8    0.6
     [9,]   14.2  -10.2   -4.8    0.6   -6.4
    [10,]  -10.2   -4.8    0.6   -6.4    9.7
    [11,]   -4.8    0.6   -6.4    9.7   -3.1
    [12,]    0.6   -6.4    9.7   -3.1   -5.7
    [13,]   -6.4    9.7   -3.1   -5.7   -4.4
    [14,]    9.7   -3.1   -5.7   -4.4    1.8
    [15,]   -3.1   -5.7   -4.4    1.8    3.5
    [16,]   -5.7   -4.4    1.8    3.5    5.4
    [17,]   -4.4    1.8    3.5    5.4   -1.4
    [18,]    1.8    3.5    5.4   -1.4    3.1
    [19,]    3.5    5.4   -1.4    3.1   -1.7
    [20,]    5.4   -1.4    3.1   -1.7   -5.3
    [21,]   -1.4    3.1   -1.7   -5.3   -1.1
    [22,]    3.1   -1.7   -5.3   -1.1   -0.1
    [23,]   -1.7   -5.3   -1.1   -0.1   -3.7
    [24,]   -5.3   -1.1   -0.1   -3.7   15.5
    [25,]   -1.1   -0.1   -3.7   15.5    7.2
    [26,]   -0.1   -3.7   15.5    7.2   -8.6
    

    Data:

    df <- read.table(text = "
    disp1   disp2   disp3
    -2.5    -4.8    -1.4
    1.3 0.6 3.1
    -1.7    -6.4    -1.7
    -8.9    9.7 -5.3
    -5  -3.1    -1.1
    -4.8    -5.7    -0.1
    -7.7    -4.4    -3.7
    3.4 1.8 15.5
    14.2    3.5 7.2
    -10.2   5.4 -8.6", h = T)