Home > OS >  Separate rows to make dummy rows
Separate rows to make dummy rows

Time:03-18

Consider this dataframe:

dat <- structure(list(col1 = c(1, 2, 0), col2 = c(0, 3, 2), col3 = c(1, 2, 3)), class = "data.frame", row.names = c(NA, -3L))

  col1 col2 col3
1    1    0    1
2    2    3    2
3    0    2    3

How can one dummify rows? i.e. whenever there is a row with more than 1 non-0 value, separate the row into multiple rows with one non-0 value per row.

In this case, this would be:

  col1 col2 col3
1    1    0    0
2    0    0    1
3    2    0    0
4    0    3    0
5    0    0    2
6    0    2    0
7    0    0    3

CodePudding user response:

You can do:

library(tidyverse)

dat |> 
  pivot_longer(everything()) |> 
  mutate(id = 1:n()) |> 
  pivot_wider(values_fill = 0) |> 
  filter(!if_all(-id, ~ . == 0)) |> 
  select(-id)

# A tibble: 7 x 3
   col1  col2  col3
  <dbl> <dbl> <dbl>
1     1     0     0
2     0     0     1
3     2     0     0
4     0     3     0
5     0     0     2
6     0     2     0
7     0     0     3

CodePudding user response:

Another approach, here I used data.table

library(data.table)

x <- rbindlist(apply(dat, 1, function(x) {
  x <- data.table(diag(x, ncol(dat)))
  x[colSums(x) > 0]
}))

setnames(x, names(dat))

x

#    col1 col2 col3
# 1:    1    0    0
# 2:    0    0    1
# 3:    2    0    0
# 4:    0    3    0
# 5:    0    0    2
# 6:    0    2    0
# 7:    0    0    3

CodePudding user response:

A very ugly way is:

library(tidyverse)

dat %>% 
  apply(1, diag) %>% 
  matrix(nrow = 3) %>% 
  t() %>% 
  as.data.frame() %>% 
  rename_with(~ names(dat), everything()) %>% 
  filter(rowSums(.) != 0)

  col1 col2 col3
1    1    0    0
2    0    0    1
3    2    0    0
4    0    3    0
5    0    0    2
6    0    2    0
7    0    0    3
  • Related