我有一个购物篮格式的数据框,如下所示:
V1 <- c('milk', 'beer', 'wrench', 'milk' )
V2 <- c('eggs', 'elbow grease', '', 'beer')
V3 <- c('water', '', '', '')
df <- data.frame(V1, V2, V3)
输出:
V1 V2 V3
1 milk eggs water
2 beer elbow grease
3 wrench
4 milk beer
我想产生的是一个单一格式的数据框,如下所示:
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)
}
我曾考虑过使用apply
将此功能应用于每一行,但是对于如何将多个结果行绑定到前一行的结果感到困惑。
答案 0 :(得分:3)
您可以使用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
注意::简单的rgex只能从ind
列中提取数字,即
df1$ind <- gsub('\\D+', '', df1$ind)
这将给
values ind 1 milk 1 2 eggs 1 3 water 1 4 beer 2 5 elbow grease 2 7 wrench 3 10 milk 4 11 beer 4
答案 1 :(得分:1)
使用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_character_。其次,它创建一个具有行ID的变量“ transaction”。第三,它将数据从宽格式转换为长格式,并使用NA_character_删除行。最后,它根据“事务”排列数据。
答案 2 :(得分:1)
或data.table方法 (单线)
首先从行名setDT(df)[, transaction := .I ]
获取交易
然后使用事务作为id列融化:melt( ... , id = "transaction" )
最后删除空值并返回第一和第三列:...[!value == "", c(1,3) ]
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
答案 3 :(得分:1)
用适当的格式""
替换字符NA
后,您可以创建一个新的列事务,然后使用reshape2::melt
:
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
此功能的好处是它将为您提供一列variable
,该列为您提供了前df
个data.frame的列的名称。如果与您无关,请使用df$variable <- NULL
删除此列。如果您还想通过增加交易顺序对结果进行排序:
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
答案 4 :(得分:0)
另一种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"