2016-10-12 5 views
0

У меня есть набор данных, который содержит Billno и столбцов продукта в следующем формате:Разделить набор данных в R

Billno Product 
1  123 
1  176 
2  189 
3  1 
3  2 
3  44 
3  46 

т.д.

Вывод должен быть таблица вида:

Billno Prod1 Prod2 Prod3 Prod4 
1  123 176 
2  189 
3  1  2  44  46 

Функция Split работает, но набор данных содержит более миллиона записей. Есть ли эффективный способ сделать это?

ответ

2

с dplyr:

library(dplyr) 
library(tidyr) 

bill <- rep(c(1,1,2,3,3,3,3),5) 
prod <- rep(c(123,176,189, 1,2,44,46),5) 

df <- data.frame(bill=bill, prod=prod) 
#determine max product count (number of columns in result) 
prodmax <- df %>% group_by(bill) %>% summarise(n = n()) 

df %>% group_by(bill) %>% 
    mutate(prodn = paste0("prod",row_number())) %>% 
    spread(prodn, prod) %>% 
#select columns in correct order 
    select_(.dots = c('bill',paste0('prod',seq(1,max(prodmax$n))))) 

результатов в:

 bill prod1 prod2 prod3 prod4 
(dbl) (dbl) (dbl) (dbl) (dbl) 
1  1  123 176 NA NA 
2  2  189 NA NA NA 
3  3   1  2 44 46 
+0

Эй @ Wietze314 спасибо много ... Это дает результат гораздо быстрее, чем другие решения .. но столбцы упорядочиваются prod1 prod10 prod11 на выходе ... как я измените порядок на prod1 prod2 prod3 ...... без ручного указания номеров столбцов – AB6

+0

Я изменил решение. Это один из способов убедиться, что столбцы (упорядоченные по алфавиту по умолчанию) находятся в правильном порядке. Другим решением было бы убедиться, что столбцы в алфавитном порядке уже правильны (то есть prod01, prod02, ..., prod11 и т. Д.), – Wietze314

0

Вы можете сделать

df <- read.table(header=T, text="Billno Product 
1  123 
1  176 
2  189 
3  1 
3  2 
3  44 
3  46") 
lst <- split(df[,-1], df[,1]) 
lst <- lapply(lst, "length<-", max(lengths(lst))) 
df <- as.data.frame(do.call(rbind, lst)) 
# V1 V2 V3 V4 
# 1 123 176 NA NA 
# 2 189 NA NA NA 
# 3 1 2 44 46 

, а затем

names(df) <- sub("V", "prod", names(df)) 
df$billno <- rownames(df) 
0

Это также будет делать:

l <- lapply(split(df, df$Billno), function(x) t(x)[2,]) 
df <- as.data.frame(do.call(rbind, lapply(lapply(l, unlist), "[", 
         1:(max(unlist(lapply(l, length))))))) 
names(df) <- paste('Prod', 1:ncol(df), sep='') 
df 
    Prod1 Prod2 Prod3 Prod4 
1 123 176 NA NA 
2 189 NA NA NA 
3  1  2 44 46 
Смежные вопросы