Convert data frame to list of lists by row

I posted this over on code review but then I remembered this new site which might be more appropriate.

I am rewriting some old code where I take a dataframe in r and convert it using the tidyverse packages to a list of lists, where each element is one row of the original dataframe - which is itself a list with each column an element. This is then passed into a htmlwidget.

My previous function achieved it like so:

feat <- function(coords, height = 20, vjust = 75,  fill = "orange"){
  inst <- purrr::flatten(purrr::by_row(coords, ..f = function(x) 
    rec <- list(type = "rect", 
                x = as.numeric(x[1]), 
                y = vjust, 
                width = as.numeric(x[2]-x[1]),
                height = height, 
                fill = fill), 
    .labels = FALSE))
  return(inst)
}

However by_row() has been depreciated from the purrr package and so I would like to rewrite the function. This is my attempt:

feat2 <- function(coords, height = 20, vjust = 75,  fill = "orange"){
  inst <- coords %>% 
    mutate(type = "rect", 
           x = as.numeric(start), 
           y = vjust, 
           width = as.numeric(end-start),
           height = height, 
           fill = fill) %>%
    select(-start, -end) %>% 
    mutate(count = 1:n()) %>%
    nest(-count) %>%
    select(-count) %>% 
    mutate(data = map(data, ~ flatten(.x))) %>% pull()
  return(inst)
}

which does the job but I feel there should be a quicker, more elegant way to achieve this. Does anyone have any ideas on this?

Here is an example data set:

coords <- structure(list(start = c(126, 433, 603, 1604), end = c(327, 495, 
644, 1831)), .Names = c("start", "end"), row.names = c(NA, -4L
), class = "data.frame")

and the desired output:

result <- list(structure(list(type = "rect", x = 126, y = 75, width = 201, 
    height = 20, fill = "blue"), .Names = c("type", "x", "y", 
"width", "height", "fill")), structure(list(type = "rect", x = 433, 
    y = 75, width = 62, height = 20, fill = "blue"), .Names = c("type", 
"x", "y", "width", "height", "fill")), structure(list(type = "rect", 
    x = 603, y = 75, width = 41, height = 20, fill = "blue"), .Names = c("type", 
"x", "y", "width", "height", "fill")), structure(list(type = "rect", 
    x = 1604, y = 75, width = 227, height = 20, fill = "blue"), .Names = c("type", 
"x", "y", "width", "height", "fill")))
1 Like

The function purrr::transpose() does exactly what you are looking for. So the code looks like this:

feat3 <- function(coords, height = 20, vjust = 75, fill = "orange") {
  coords %>%
    # transmute keeps only the columns specified, so there is no need to
    # deselect start and end afterwards
    transmute(
      type = "rect",
      x = as.numeric(start),
      y = vjust,
      width = as.numeric(end - start),
      height = height,
      fill = fill
    ) %>%
    purrr::transpose()
}
4 Likes

Awesome!! Thank You!

1 Like