我有一个带有ID号的数据框,一个产品变量和一个虚拟变量,该变量指示是否购买了产品。
set.seed(2019)
library(dplyr)
library(data.table)
df <- data.frame(id = rep.int(c(1:5), 5),
bought = 1) %>%
group_by(id) %>%
mutate(product = c("244.1","455.2","266.3","777.4","111.1"))
除此之外,我还有一个向量,其中包含我想添加到数据框中的我尚未购买的产品。
products <- c("100.4", "500.1", "200.1", "121.6", "251.7", "215.1", "172.2")
也就是说,对于每个用户,我都希望购买非购买产品并设置购买= 0。
一种方法是从向量中创建一个数据帧并将其绑定到原始数据帧。
products <- data.frame(product = products)
products$id <- NA
products$bought <- 0
products <- products[, c(2, 3, 1)]
df <- bind_rows(df, products)
#> Warning in bind_rows_(x, .id): binding character and factor vector,
#> coercing into character vector
然后,我可以使用data.table
来完成表格,转动每个NA = 0
,如果我想用id = NA
过滤掉每个观测值。 (我也可以使用tidyr::complete()
,但是原始data.frame非常大,所以我更喜欢data.table
)
setDT(df)[CJ(id = id, product = product, unique = TRUE), on = .(id, product)][
is.na(bought), bought := 0][]
#> id bought product
#> 1: NA 0 100.4
#> 2: NA 0 111.1
#> 3: NA 0 121.6
#> 4: NA 0 172.2
#> 5: NA 0 200.1
#> 6: NA 0 215.1
#> 7: NA 0 244.1
#> 8: NA 0 251.7
#> 9: NA 0 266.3
#> 10: NA 0 455.2
#> 11: NA 0 500.1
#> 12: NA 0 777.4
#> 13: 1 0 100.4
#> 14: 1 1 111.1
#> 15: 1 0 121.6
但是,从向量创建data.frame的方法似乎很冗长,我宁愿不使用id = NA
添加行。有没有更整洁的方法来将向量与data.frame结合起来并完成它?
由reprex package(v0.2.1)于2019-01-08创建
答案 0 :(得分:1)
使用data.table的简单解决方案:
products <- c("100.4", "500.1", "200.1", "121.6", "251.7", "215.1", "172.2")
df <- setDT(df)
rbindlist(lapply(unique(df$id),function(ID){
rbind(df[id == ID],data.table(product = products,id = ID, bought = 0))
}))
您还可以考虑使用该dtaa框架合并两个数据框架:
products <- data.frame(product = rep(products,each = length(unique(df$id))),
id = rep(unique(df$id),length(unique(products))))