Home > Mobile >  Transform data from a column into multiple columns with Tidyverse
Transform data from a column into multiple columns with Tidyverse

Time:05-05

So I scraped a website and the data looks like this:

# A tibble: 150 x 1
   data                                                                              
   <chr>                                                                             
 1 HELSFYR / HOVINENGA - Leilighet fra 2019 med balkong, garasjeplass og el-billading
 2 Innspurten 10B, Oslo                                                              
 3 56 m²17 500 kr                                                                    
 4 Fin 3-roms leilighet til leie på Grunerløkka                                      
 5 SANNERGATA 13 A, Oslo                                                             
 6 55 m²14 200 kr                                                                    
 7 Torshov Torg - Meget pen 3-roms med balkong Sandakerveien 22 B, 0473 Oslo         
 8 SANDAKERVEIEN 22 B, Oslo                                                          
 9 51 m²16 500 kr                                                                    
10 FROGNER/VIKA- 3-roms leilighet med god standard. Ledig 1 juli!                    
# ... with 140 more rows

It actually contains three columns that I need. How to I transform a column into multiple, with every 1-3 row split into them? The desired output would be:

# A tibble: 3 x 3
  title                                          adress                   info          
  <chr>                                          <chr>                    <chr>         
1 "HELSFYR / HOVINENGA - Leilighet fra 2019 "    Innspurten 10B, Oslo     56 m²17 500 kr
2 "Fin 3-roms leilighet til leie på Grunerløkka" SANNERGATA 13 A, Oslo    55 m²14 200 kr
3 "Torshov Torg - Meget pen 3-roms med balko"    SANDAKERVEIEN 22 B, Oslo 51 m²16 500 kr

My data

Dput()

structure(list(data = c("HELSFYR / HOVINENGA - Leilighet fra 2019 med balkong, garasjeplass og el-billading", 
"Innspurten 10B, Oslo", "56 m²17 500 kr", "Fin 3-roms leilighet til leie på Grunerløkka", 
"SANNERGATA 13 A, Oslo", "55 m²14 200 kr", "Torshov Torg - Meget pen 3-roms med balkong Sandakerveien 22 B, 0473 Oslo", 
"SANDAKERVEIEN 22 B, Oslo", "51 m²16 500 kr")), row.names = c(NA, 
-9L), class = c("tbl_df", "tbl", "data.frame"))

CodePudding user response:

You could do:

df$data %>% 
  matrix(nrow = 3) %>% 
  t() %>% 
  as.data.frame() %>% 
  setNames(c("Title", "Address", "Info")) %>% 
  as_tibble()
#> # A tibble: 3 x 3
#>   Title                                                            Address Info 
#>   <chr>                                                            <chr>   <chr>
#> 1 HELSFYR / HOVINENGA - Leilighet fra 2019 med balkong, garasjepl~ Innspu~ 56 m~
#> 2 Fin 3-roms leilighet til leie på Grunerløkka                     SANNER~ 55 m~
#> 3 Torshov Torg - Meget pen 3-roms med balkong Sandakerveien 22 B,~ SANDAK~ 51 m~

Created on 2022-05-04 by the reprex package (v2.0.1)

CodePudding user response:

While I like @Allan Cameron's solution most. Here is tidyverse approach: This one will additionally remove in the title column everything that comes after the comma:

library(dplyr)
library(tidyr)
library(stringr)

df %>% 
  group_by(group = as.integer(gl(n(), 3, n()))) %>% 
  summarise(helper = paste(data, collapse = "|")) %>% 
  separate(helper, c("title", "adress", "info"), sep = "\\|", remove = TRUE) %>% 
  ungroup() %>% 
  select(-group) %>% 
  mutate(title = str_remove_all(title, '\\,.*'))
  
   title                                                          adress                   info          
  <chr>                                                          <chr>                    <chr>         
1 HELSFYR / HOVINENGA - Leilighet fra 2019 med balkong           Innspurten 10B, Oslo     56 m²17 500 kr
2 Fin 3-roms leilighet til leie på Grunerløkka                   SANNERGATA 13 A, Oslo    55 m²14 200 kr
3 Torshov Torg - Meget pen 3-roms med balkong Sandakerveien 22 B SANDAKERVEIEN 22 B, Oslo 51 m²16 500 kr

CodePudding user response:

You can do this:

setNames(
  bind_cols(lapply(1:3, function(i) data[seq(i,nrow(data),3),])),
  c("title","address","info")
)

Output:

  title                                                                              address                  info          
  <chr>                                                                              <chr>                    <chr>         
1 HELSFYR / HOVINENGA - Leilighet fra 2019 med balkong, garasjeplass og el-billading Innspurten 10B, Oslo     56 m²17 500 kr
2 Fin 3-roms leilighet til leie på Grunerløkka                                       SANNERGATA 13 A, Oslo    55 m²14 200 kr
3 Torshov Torg - Meget pen 3-roms med balkong Sandakerveien 22 B, 0473 Oslo          SANDAKERVEIEN 22 B, Oslo 51 m²16 500 kr

CodePudding user response:

You can use the scan() function and use the what argument to define the fields:

tibble::as_tibble(scan(text = df$data, what = list(title = "", address = "", info = ""), sep = "\n"))

Read 3 records
# A tibble: 3 × 3
  title                                                                              address                  info          
  <chr>                                                                              <chr>                    <chr>         
1 HELSFYR / HOVINENGA - Leilighet fra 2019 med balkong, garasjeplass og el-billading Innspurten 10B, Oslo     56 m²17 500 kr
2 Fin 3-roms leilighet til leie på Grunerløkka                                       SANNERGATA 13 A, Oslo    55 m²14 200 kr
3 Torshov Torg - Meget pen 3-roms med balkong Sandakerveien 22 B, 0473 Oslo          SANDAKERVEIEN 22 B, Oslo 51 m²16 500 kr

It's possible that you could also solve this upstream while scraping the data.

  • Related