In this approach we convert the data to long form using separate_rows
, transform it using transform
and convert back to wide form using reshape
. We use a mix of dplyr, tidyr and base functions choosing among them based on which ever gives shorter code.
1) Add a P column which is the same as prices, separate the prices column into rows, add a column row which numbers the rows and n which numbers them within prices and then convert to wide form. reshape is a bit less code than pivot_wider in this case but the latter could have been used. Also we use transform which is like mutate except it outputs a data frame which we need for reshape. At the end select out what we need.
library(dplyr)
library(tidyr)
DF %>%
mutate(P = prices, prices = gsub("\\$", "", prices), row = 1:n()) %>%
separate_rows(prices, sep = " +") %>%
transform(n = ave(1:nrow(.), row, FUN = seq_along)) %>%
reshape(dir = "wide", idvar = c("row", "P"), timevar = "n", sep = "") %>%
select(prices = P, everything(), -row)
giving:
prices prices1 prices2 prices3
1 $1,50 $1,20 1,50 1,20 <NA>
3 $1,50 1,50 <NA> <NA>
4 $1,75 $1,25 $1,35 1,75 1,25 1,35
2) If you want the prices column converted to numeric and if decimal point is dot in the current locale then use this which replaces the commas with dots and adds convert=TRUE
to separate_rows
. If comma is the decimal point in the current locale then omit the second mutate
below.
DF %>%
mutate(P = prices, prices = gsub("\\$", "", prices),
prices = gsub(",", ".", prices),
row = 1:n()) %>%
separate_rows(prices, sep = " +", convert = TRUE) %>%
transform(n = ave(1:nrow(.), row, FUN = seq_along)) %>%
reshape(dir = "wide", idvar = c("row", "P"), timevar = "n", sep = "") %>%
select(prices = P, everything(), -row)
Note
The input in reproducible form:
DF <-
structure(list(prices = c("$1,50 $1,20", "$1,50", "$1,75 $1,25 $1,35"
)), class = "data.frame", row.names = c(NA, -3L))