2016-10-29 2 views
0

У меня есть кадр данных с тремя столбцами, который фиксирует транзакционные данные, включая CustomerName, OrderDate и имя приобретенных Продуктов. Я должен преобразовать dataframe в другой фрейм данных с таким форматом, что все предметы, купленные клиентом за одну дату, находятся в одной строке.R Преобразование данных

Поскольку я имею дело с большим набором данных, есть эффективный способ для этого преобразования, надеюсь, без использования для циклов.

Кроме того, количество столбцов для продуктов в кадре данных должно быть равно максимальному количеству продуктов, купленных любым клиентом в любой день. Вы можете найти пример кадра данных до и после преобразования

исходные данные:

data <- data.frame(Customer = c("John", "John", "John", "Tom", "Tom", "Tom", "Sally", "Sally", "Sally", "Sally"), 
        OrderDate = c("1-Oct", "2-Oct", "2-Oct", "2-Oct","2-Oct", "2-Oct", "3-Oct", "3-Oct", "3-Oct", "3-Oct"), 
        Product = c("Milk", "Eggs", "Bread", "Chicken", "Pizza", "Beer", "Salad", "Apples", "Eggs", "Wine"), 
        stringsAsFactors = FALSE) 

# Customer OrderDate Product 
# 1  John  1-Oct Milk 
# 2  John  2-Oct Eggs 
# 3  John  2-Oct Bread 
# 4  Tom  2-Oct Chicken 
# 5  Tom  2-Oct Pizza 
# 6  Tom  2-Oct Beer 
# 7  Sally  3-Oct Salad 
# 8  Sally  3-Oct Apples 
# 9  Sally  3-Oct Eggs 
# 10 Sally  3-Oct Wine 

после превращения:

datatransform <- as.data.frame(matrix(NA, nrow = 4, ncol = 6)) 
colnames(datatransform) <- c("Customer", "OrderDate", "Product1", "Product2", "Product3", "Product4") 
datatransform$Customer <- c("John", "John", "Tom", "Sally") 
datatransform$OrderDate <- c("1-Oct", "2-Oct", "2-Oct", "3-Oct") 
datatransform[1, 3:6] <- c("Milk", "", "", "") 
datatransform[2, 3:6 ] <- c("Eggs", "Bread", "", "") 
datatransform[3, 3:6 ] <- c("Chicken", "Pizza", "Beer", "") 
datatransform[4, 3:6 ] <- c("Salad", "Apples", "Eggs", "Wine") 

# Customer OrderDate Product1 Product2 Product3 Product4 
# 1  John  1-Oct  Milk       
# 2  John  2-Oct  Eggs Bread     
# 3  Tom  2-Oct Chicken Pizza  Beer   
# 4 Sally  3-Oct Salad Apples  Eggs  Wine 

Кроме того, число столбцов для продуктов в кадре данных должно быть равно максимальному количеству продуктов, купленных любым клиентом в любой день.

+0

, поскольку у вас есть дубликаты в течение дня, добавьте новую переменный время, и это базовое долгосрочное преобразование: 'data $ time <- ave (данные $ Customer, данные $ Customer, FUN = seq_along); reshape (data, dir = 'wide', idvar = c ('Customer', 'OrderDate')) ' – rawr

+0

Спасибо, rawr, за подсказку! ваше решение разрешает большую часть проблемы. однако для Джона на октябрь, у него есть NA в Product1, Eggs в продукте 2 и Bread в продукте3. Я хотел бы иметь яйца в продукте1 и хлеб в продукте 2. есть ли способ исправить это с помощью изменения или иначе? – xineers

+0

Я должен был сгруппироваться как по клиенту, так и по дате 'data $ time <- с (данные, ave (Customer, list (Customer, OrderDate), FUN = seq_along))' – rawr

ответ

0

Поскольку вы говорили о большом наборе данных (то эффективность является очень важным вопросом тока во внимание), вот dplyr и reshape2 решение:

library(reshape2) 
library(dplyr) 

data %>% group_by(Customer, OrderDate) %>% 
      mutate(ProductValue = paste0("Product", 1:n())) %>% 
      dcast(Customer + OrderDate ~ ProductValue, value.var = "Product" ) %>% 
      arrange(OrderDate) 

    Customer OrderDate Product1 Product2 Product3 Product4 
1  John  1-Oct  Milk  <NA>  <NA>  <NA> 
2  John  2-Oct  Eggs Bread  <NA>  <NA> 
3  Tom  2-Oct Chicken Pizza  Beer  <NA> 
4 Sally  3-Oct Salad Apples  Eggs  Wine 
+0

благодарим вас обоих за аккуратные решения. Решение dplyr/reshape2 выполняется быстро на большом наборе данных! – xineers