Roy*_*lTS 14 r data.table tidyr tidyverse
tidyr::complete()将行添加到a data.frame中,以获取数据中缺少的列值组合.例:
library(dplyr)
library(tidyr)
df <- data.frame(person = c(1,2,2),
observation_id = c(1,1,2),
value = c(1,1,1))
df %>%
tidyr::complete(person,
observation_id,
fill = list(value=0))
Run Code Online (Sandbox Code Playgroud)
产量
# A tibble: 4 × 3
person observation_id value
<dbl> <dbl> <dbl>
1 1 1 1
2 1 2 0
3 2 1 1
4 2 2 1
Run Code Online (Sandbox Code Playgroud)
其中value组合person == 1和observation_id == 2缺少的组合df已填入值0.
什么相当于这个data.table?
Fra*_*ank 13
我认为data.table的原理需要的特殊功能少于你在tidyverse中找到的任务,因此需要一些额外的编码,例如:
res = setDT(df)[
CJ(person = person, observation_id = observation_id, unique=TRUE),
on=.(person, observation_id)
]
Run Code Online (Sandbox Code Playgroud)
在此之后,您仍然必须手动处理缺失级别的值的填充.关注@ thelatemail的评论:
res[is.na(value), value := 0 ]
Run Code Online (Sandbox Code Playgroud)
当然,这里的列名必须输入三次才是疯狂的.但另一方面,可以写一个包装器:
completeDT <- function(DT, cols, defs = NULL){
mDT = do.call(CJ, c(DT[, ..cols], list(unique=TRUE)))
res = DT[mDT, on=names(mDT)]
if (length(defs))
res[, names(defs) := Map(replace, .SD, lapply(.SD, is.na), defs), .SDcols=names(defs)]
res[]
}
completeDT(setDT(df), cols = c("person", "observation_id"), defs = c(value = 0))
person observation_id value
1: 1 1 1
2: 1 2 0
3: 2 1 1
4: 2 2 1
Run Code Online (Sandbox Code Playgroud)
作为避免第一步输入名称三次的快速方法,这里是@thelatemail的想法:
vars <- c("person","observation_id")
df[do.call(CJ, c(mget(vars), unique=TRUE)), on=vars]
# or with magrittr...
c("person","observation_id") %>% df[do.call(CJ, c(mget(.), unique=TRUE)), on=.]
Run Code Online (Sandbox Code Playgroud)
更新:现在您不需要在CJ中输入两次名称,这要归功于@MichaelChirico和@MattDowle 的改进.
那里可能有更好的答案,但这有效:
dt[CJ(person=unique(dt$person),
observation_id=unique(dt$observation_id)),
on=c('person','observation_id')]
Run Code Online (Sandbox Code Playgroud)
这使:
person observation_id value
1: 1 1 1
2: 2 1 1
3: 1 2 NA
4: 2 2 1
Run Code Online (Sandbox Code Playgroud)
现在,如果您希望能够填充任何值(而不是NA),我建议您等待相应的功能完成或对其做出贡献:)