通过用 R 中所有可能值的集合替换缺失值来扩展 data.frame
Expanding a data.frame by replacing missing values with set of all possible values in R
我想通过用所有可能行的集合替换每个不完整的行来扩展我的数据集。有人对执行此操作的有效方法有任何建议吗?
例如,假设 X 和 Z 都可以取值 0 或 1。
输入:
id y x z
1 1 0 0 NA
2 2 1 NA 0
3 3 0 1 1
4 4 1 NA NA
输出:
id y x z
1 1 0 0 0
2 1 0 0 1
3 2 1 0 0
4 2 1 1 0
5 3 0 1 1
6 4 1 0 0
7 4 1 0 1
8 4 1 1 0
9 4 1 1 1
目前我只是逐行处理原始数据集:
for(i in 1:N){
if(is.na(temp.dat$x[i]) & !is.na(temp.dat$z[i])){
augment <- matrix(rep(temp.dat[i,],2),ncol=ncol(temp.dat),byrow=TRUE)
augment[,3] <- c(0,1)
}else
if(!is.na(temp.dat$x[i]) & is.na(temp.dat$z[i])){
augment <- matrix(rep(temp.dat[i,],2),ncol=ncol(temp.dat),byrow=TRUE)
augment[,4] <- c(0,1)
}else{
if(is.na(temp.dat$x[i]) & is.na(temp.dat$z[i])){
augment <- matrix(rep(temp.dat[i,],4),ncol=ncol(temp.dat),byrow=TRUE)
augment[,3] <- c(0,0,1,1)
augment[,4] <- c(0,1,0,1)
}
}
你可以试试
在每行中创建一个“NA”计数的“索引”(rowSums(is.na(...)
)
使用“index”扩展原始数据集的行数(df[rep(1:nrow...
)
循环(sapply
)“indx”并将其用作rep
中的“times”参数,然后对值[=17]执行expand.grid
=] 创建“lst”
split
扩展数据集“df1”,按“id”
使用Map
将“lst2”中相应的“NA”值更改为“lst”中的值
rbind
列表元素
indx <- rowSums(is.na(df[-1]))
df1 <- df[rep(1:nrow(df), 2^indx),]
lst <- sapply(indx, function(x) expand.grid(rep(list(0:1), x)))
lst2 <- split(df1, df1$id)
res <- do.call(rbind,Map(function(x,y) {x[is.na(x)] <- as.matrix(y);x},
lst2, lst))
row.names(res) <- NULL
res
# id y x z
#1 1 0 0 0
#2 1 0 0 1
#3 2 1 0 0
#4 2 1 1 0
#5 3 0 1 1
#6 4 1 0 0
#7 4 1 1 0
#8 4 1 0 1
#9 4 1 1 1
数据
df <- structure(list(id = 1:4, y = c(0L, 1L, 0L, 1L), x = c(0L, NA,
1L, NA), z = c(NA, 0L, 1L, NA)), .Names = c("id", "y", "x", "z"
), class = "data.frame", row.names = c("1", "2", "3", "4"))
我想通过用所有可能行的集合替换每个不完整的行来扩展我的数据集。有人对执行此操作的有效方法有任何建议吗?
例如,假设 X 和 Z 都可以取值 0 或 1。
输入:
id y x z
1 1 0 0 NA
2 2 1 NA 0
3 3 0 1 1
4 4 1 NA NA
输出:
id y x z
1 1 0 0 0
2 1 0 0 1
3 2 1 0 0
4 2 1 1 0
5 3 0 1 1
6 4 1 0 0
7 4 1 0 1
8 4 1 1 0
9 4 1 1 1
目前我只是逐行处理原始数据集:
for(i in 1:N){
if(is.na(temp.dat$x[i]) & !is.na(temp.dat$z[i])){
augment <- matrix(rep(temp.dat[i,],2),ncol=ncol(temp.dat),byrow=TRUE)
augment[,3] <- c(0,1)
}else
if(!is.na(temp.dat$x[i]) & is.na(temp.dat$z[i])){
augment <- matrix(rep(temp.dat[i,],2),ncol=ncol(temp.dat),byrow=TRUE)
augment[,4] <- c(0,1)
}else{
if(is.na(temp.dat$x[i]) & is.na(temp.dat$z[i])){
augment <- matrix(rep(temp.dat[i,],4),ncol=ncol(temp.dat),byrow=TRUE)
augment[,3] <- c(0,0,1,1)
augment[,4] <- c(0,1,0,1)
}
}
你可以试试
在每行中创建一个“NA”计数的“索引”(
rowSums(is.na(...)
)使用“index”扩展原始数据集的行数(
df[rep(1:nrow...
)循环(
sapply
)“indx”并将其用作rep
中的“times”参数,然后对值[=17]执行expand.grid
=] 创建“lst”split
扩展数据集“df1”,按“id”使用
Map
将“lst2”中相应的“NA”值更改为“lst”中的值rbind
列表元素indx <- rowSums(is.na(df[-1])) df1 <- df[rep(1:nrow(df), 2^indx),] lst <- sapply(indx, function(x) expand.grid(rep(list(0:1), x))) lst2 <- split(df1, df1$id) res <- do.call(rbind,Map(function(x,y) {x[is.na(x)] <- as.matrix(y);x}, lst2, lst)) row.names(res) <- NULL res # id y x z #1 1 0 0 0 #2 1 0 0 1 #3 2 1 0 0 #4 2 1 1 0 #5 3 0 1 1 #6 4 1 0 0 #7 4 1 1 0 #8 4 1 0 1 #9 4 1 1 1
数据
df <- structure(list(id = 1:4, y = c(0L, 1L, 0L, 1L), x = c(0L, NA,
1L, NA), z = c(NA, 0L, 1L, NA)), .Names = c("id", "y", "x", "z"
), class = "data.frame", row.names = c("1", "2", "3", "4"))