R 将篮子数据帧融化为单个数据帧,无循环

R 将篮子数据帧融化为单个数据帧,无循环,r,market-basket-analysis,R,Market Basket Analysis,我有一个篮子格式的数据帧,如下所示: V1 <- c('milk', 'beer', 'wrench', 'milk' ) V2 <- c('eggs', 'elbow grease', '', 'beer') V3 <- c('water', '', '', '') df <- data.frame(V1, V2, V3) 我想制作一个单一格式的数据帧,如下所示: transaction product 1 1 milk 2

我有一个篮子格式的数据帧,如下所示:

V1 <- c('milk', 'beer', 'wrench', 'milk' )
V2 <- c('eggs', 'elbow grease', '', 'beer')
V3 <- c('water', '', '', '')

df <- data.frame(V1, V2, V3)
我想制作一个单一格式的数据帧,如下所示:

  transaction   product
1           1   milk
2           1   eggs
3           1   water
4           2   beer
5           2   elbow grease
6           3   wrench
7           4   milk
8           4   beer
现在,我想要数据帧中的数据,以便在切换到apriori R包使用的事务格式之前进行过滤

将此数据帧从篮子转换为单一格式的最快方法是什么

现在我正在使用一个非常慢的循环

dfSingle <- data.frame(product = character(),
                    transaction = integer())
for (row in 1:nrow(df))  {
  # Create a list of products
  productList <- unname(unlist(df[row, ]))

  # Remove blank spaces
  productList <- productList[!productList %in% ""]

  # Convert to a dataframe
  dfTemp <- as.data.frame(productList)
  colnames(dfTemp) <- "product"
  dfTemp$transaction <- row

  # Bind to larger dataframe with previous rows
  dfSingle <- rbind(dfSingle, dfTemp)

}

dfSingle您可以使用
stack
。诀窍是转置数据帧,即

df1 <- stack(as.data.frame(t(df), stringsAsFactors = FALSE))

df1[df1$values != '',]
         values ind
#1          milk  V1
#2          eggs  V1
#3         water  V1
#4          beer  V2
#5  elbow grease  V2
#7        wrench  V3
#10         milk  V4
#11         beer  V4
这将给


使用
tidyverse
可以执行以下操作:

df %>%
 mutate_all(funs(ifelse(. == "", NA_character_, paste0(.)))) %>%
 rowid_to_column(var = "transaction") %>%
 gather(var, product, -transaction, na.rm = TRUE) %>%
 select(-var) %>%
 arrange(transaction)

  transaction      product
1           1         milk
2           1         eggs
3           1        water
4           2         beer
5           2 elbow grease
6           3       wrench
7           4         milk
8           4         beer
首先,它用NA_字符替换空行。其次,它创建了一个行ID为“transaction”的变量。第三,它将数据从宽格式转换为长格式,并删除带有NA_字符的行。最后,它根据“事务”或data.table方法排列数据 (一班轮)

首先从以下行名称获取事务:
setDT(df)[,事务:=.I]
然后使用事务作为id列进行熔化:
melt(…,id=“transaction”)
最后删除空值并返回第一列和第三列:
…[!value==”,c(1,3)]


将字符
替换为适当的格式
NA
后,可以创建一个新的列事务,然后使用
重塑2::melt

df[df == ""]   <- NA    
df$transaction <- 1:nrow(df)

此函数的好处是,它将为您提供一个列
变量
,它将为您提供上一个
df
data.frame的列的名称。如果它与您无关,则使用另一个基础
R
备选方案删除此列:

do.call(
  rbind, 
  sapply(seq_along(df), function(i) cbind(transaction = i, product = df[[i]][nzchar(df[[i]])])) 
)

     transaction product       
[1,] "1"         "milk"        
[2,] "1"         "beer"        
[3,] "1"         "wrench"      
[4,] "1"         "milk"        
[5,] "2"         "eggs"        
[6,] "2"         "elbow grease"
[7,] "2"         "beer"        
[8,] "3"         "water"  

接受这个答案,因为它作为数据表运行得最快
df %>%
 mutate_all(funs(ifelse(. == "", NA_character_, paste0(.)))) %>%
 rowid_to_column(var = "transaction") %>%
 gather(var, product, -transaction, na.rm = TRUE) %>%
 select(-var) %>%
 arrange(transaction)

  transaction      product
1           1         milk
2           1         eggs
3           1        water
4           2         beer
5           2 elbow grease
6           3       wrench
7           4         milk
8           4         beer
melt( setDT(df)[, transaction := .I ], id = "transaction" )[!value == "", c(1,3) ]

#    transaction        value
# 1:           1         milk
# 2:           2         beer
# 3:           3       wrench
# 4:           4         milk
# 5:           1         eggs
# 6:           2 elbow grease
# 7:           4         beer
# 8:           1        water
df[df == ""]   <- NA    
df$transaction <- 1:nrow(df)
melted_df <- na.omit(reshape2::melt(data=df, id.vars="transaction"))
> melted_df
  transaction variable        value
1           1       V1         milk
2           2       V1         beer
3           3       V1       wrench
4           4       V1         milk
5           1       V2         eggs
6           2       V2 elbow grease
8           4       V2         beer
9           1       V3        water
out <- melted_df[order(melted_df$transaction), ]
> out
  transaction        value
1           1         milk
5           1         eggs
9           1        water
2           2         beer
6           2 elbow grease
3           3       wrench
4           4         milk
8           4         beer
do.call(
  rbind, 
  sapply(seq_along(df), function(i) cbind(transaction = i, product = df[[i]][nzchar(df[[i]])])) 
)

     transaction product       
[1,] "1"         "milk"        
[2,] "1"         "beer"        
[3,] "1"         "wrench"      
[4,] "1"         "milk"        
[5,] "2"         "eggs"        
[6,] "2"         "elbow grease"
[7,] "2"         "beer"        
[8,] "3"         "water"