重塑篮子数据框架,用于分离篮子中的物品

时间:2018-03-09 16:55:46

标签: r dplyr reshape

我使用客户购买篮子的数据集。以下是它的一个示例:

  basket item quant
1      1    B     1
2      1    A     2
3      1    C     1
4      2    A     1
5      2    C     1
6      3    A     2
7      4    B     1
8      4    C     1

以下是复制它的代码:

input <- data.frame(
    basket = c(1,1,1,2,2,3,4,4),
    item = c("B","A","C","A","C","A","B","C"),
    quant=c(1,2,1,1,1,2,1,1)
)

所以在第一个篮子中有三个具有指定数量的物品。我有一个自定义功能,只适用于特定格式的输入;我们定义最大篮子大小。让我们说它是5.现在该函数的输入应该是这样的:

  basket item_1 item_2 item_3 item_4 item_5
1      1      B      A      A      C    <NA>
2      2      A      C   <NA>   <NA>    <NA>
3      3      A      A   <NA>   <NA>    <NA>
4      4      B      C   <NA>   <NA>    <NA>

我一直试图使用dplyrsummarise来做,但没有运气。 任何帮助将不胜感激!

2 个答案:

答案 0 :(得分:2)

这是tidyverse的想法。这里的技巧是根据quant复制您的行,然后删除quant变量,这样它就不会让您重新整理到宽数据框。之后,您创建一个new变量来处理重复项,当然最后spread来获取所需的宽数据框。

library(tidyverse)

df[rep(rownames(df), df$quant),] %>% 
 select(-quant) %>% 
 group_by(basket) %>% 
 mutate(new = paste0('item_', row_number())) %>% 
 spread(new, item)

给出,

# A tibble: 4 x 5
# Groups:   basket [4]
  basket item_1 item_2 item_3 item_4
   <dbl> <fct>  <fct>  <fct>  <fct> 
1     1. B      A      A      C     
2     2. A      C      NA     NA    
3     3. A      A      NA     NA    
4     4. B      C      NA     NA 

答案 1 :(得分:2)

另一种可能的解决方案:

library(dplyr)
library(tidyr)

input[rep(1:nrow(input), input$quant),] %>% 
  group_by(basket) %>% 
  mutate(item2 = paste0('item_', row_number())) %>% 
  complete(item2 = paste0('item_', 1:5)) %>% 
  select(-quant) %>% 
  spread(item2, item)

给出:

# A tibble: 4 x 6
  basket item_1 item_2 item_3 item_4 item_5
   <dbl> <fct>  <fct>  <fct>  <fct>  <fct> 
1     1. B      A      A      C      NA    
2     2. A      C      NA     NA     NA    
3     3. A      A      NA     NA     NA    
4     4. B      C      NA     NA     NA

使用相同的逻辑,但使用data.table - 包:

library(data.table)
setDT(input)

input[input[, rep(.I, quant)]
      ][, .(basket, item, item2 = paste0('item_', rowid(basket)))
        ][CJ(basket = basket, item2 = paste0('item_', 1:5), unique = TRUE)
          , on = .(basket, item2)
          ][, dcast(.SD, basket ~ item2, value.var = 'item')]