Search code examples
rfunctionreshapedata-manipulation

Data manipulation in R: Starting a new row if i > i-1


I have a long (one row) data file with many values. It needs to be broken up into multiple rows. While the specifics of why I need to do this isn't important, the logic is that column i should always be bigger than column i+1. I.e. The values along a row should be decreasing.

The best way I can think to do this is to break up the data frame into multiple rows with an 'if then' style of function: If column i > i-1, start a new row. If i < i-1, keep this value in the row.

#Example data but with similar format to my real data

df <- data.frame(matrix(ncol = 9, nrow = 1))
df[1,] <- c(3, 2, 1, 2, 1, 1, 3, 2, 1) 

I would like it to end up looking like this.

3 2 1
2 1 
1
3 2 1

I'm not very proficient with functions referring to i position in a data frame and the kind of data manipulation this needs. Any advice would be appreciated.


Solution

  • Here is a tidy solution. Please let me know if this solves your question:

    library(tidyverse)
    
    df <- data.frame(matrix(ncol = 9, nrow = 1))
    df[1,] <- c(3, 2, 1, 2, 1, 1, 3, 2, 1) 
    
    df %>%
      pivot_longer(cols = everything(), names_to = "vars") %>%
      mutate(smaller_than_prev = value < lag(value) | is.na(lag(value)),
             num_falses = cumsum(smaller_than_prev == FALSE)) %>%
      group_by(num_falses) %>%
      mutate(row_num = row_number()) %>%
      pivot_wider(names_from = row_num, values_from = value, values_fill = NA, names_prefix = "var") %>%
      fill(c(`var1`, `var2`, `var3`), .direction = "downup") %>%
      slice_head(n = 1) %>%
      ungroup() %>%
      select(`var1`, `var2`, `var3`)