Search code examples
rpivottranspose

Changing a Column to an Observation in a Row in R


I am currently struggling to transition one of my columns in my data to a row as an observation. Below is a representative example of what my data looks like:

library(tidyverse)
test_df <- tibble(unit_name=rep("Chungcheongbuk-do"),unit_n=rep(2),
               can=c("Cho Bong-am","Lee Seung-man","Lee Si-yeong","Shin Heung-woo"),
               pev1=rep(510014),vot1=rep(457815),vv1=rep(445955),
               ivv1=rep(11860),cv1=c(25875,386665,23006,10409),
               abstention=rep(52199))

As seen above, the abstention column exists at the end of my data frame, and I would like my data to look like the following:

library(tidyverse)
desired_df <- tibble(unit_name=rep("Chungcheongbuk-do"),unit_n=rep(2),
                     can=c("Cho Bong-am","Lee Seung-man","Lee Si-yeong","Shin Heung-woo","abstention"),
                     pev1=rep(510014),vot1=rep(457815),vv1=rep(445955),
                     ivv1=rep(11860),cv1=c(25875,386665,23006,10409,52199))

Here, abstentions are treated like a candidate, in the can column. Thus, the rest of the data is maintained, and the abstention values are their own observation in the cv1 column.

I have tried using pivot_wider, but I am unsure how to use the arguments to get what I want. I have also considered t() to transpose the column into a row, but also having a hard time slotting it back into my data. Any help is appreciated! Thanks!


Solution

  • Here's a strategy what will work if you have multiple unit_names

    test_df %>% 
      group_split(unit_name) %>%
      map( function(group_data) {
        slice(group_data, 1) %>% 
          mutate(can="abstention", cv1=abstention) %>% 
          add_row(group_data, .) %>%
          select(-abstention)
      }) %>% 
      bind_rows()
    

    Basically we split the data up by unit_name, then we grab the first row for each group and move the values around. Append that as a new row to each group, and then re-combine all the groups.