在以下示例中,res
包含90行和6列,并包含多个NA。还有一个矩阵,tmpCombs
有6行2列。每行tmpCombs
对应res
中的15行组(6 * 15 = 90)。它的列数(2)意味着我必须用指定的字符(比如“B”)替换res
每行中的2个现有NA。 (确保每行至少有2个NA)。
例如,tmpCombs
第5行中的值2和4表示对于(4*15+1):(5*15)
的组61-75 res
中的每一行,第2和第4个出现的NAs必须用“B”代替。
我可以使用嵌套for循环来完成这项工作,但我正在寻找一种更快/更大的方式来执行这些替换(可能使用dplyr
或data.table
),因为我的代码变得越来越多随着尺寸的增加,速度变慢。
以下是res
和tmpCombs
的示例。还有第二个数据帧res2
,其中包含所需的输出。
res <- structure(list(X1 = c("A", "A", "A", "A", "A", NA, NA, NA, NA,
NA, NA, NA, NA, NA, NA, "A", "A", "A", "A", "A", NA, NA, NA,
NA, NA, NA, NA, NA, NA, NA, "A", "A", "A", "A", "A", NA, NA,
NA, NA, NA, NA, NA, NA, NA, NA, "A", "A", "A", "A", "A", NA,
NA, NA, NA, NA, NA, NA, NA, NA, NA, "A", "A", "A", "A", "A",
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, "A", "A", "A", "A", "A",
NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), X2 = c("A", NA, NA,
NA, NA, "A", "A", "A", "A", NA, NA, NA, NA, NA, NA, "A", NA,
NA, NA, NA, "A", "A", "A", "A", NA, NA, NA, NA, NA, NA, "A",
NA, NA, NA, NA, "A", "A", "A", "A", NA, NA, NA, NA, NA, NA, "A",
NA, NA, NA, NA, "A", "A", "A", "A", NA, NA, NA, NA, NA, NA, "A",
NA, NA, NA, NA, "A", "A", "A", "A", NA, NA, NA, NA, NA, NA, "A",
NA, NA, NA, NA, "A", "A", "A", "A", NA, NA, NA, NA, NA, NA),
X3 = c(NA, "A", NA, NA, NA, "A", NA, NA, NA, "A", "A", "A",
NA, NA, NA, NA, "A", NA, NA, NA, "A", NA, NA, NA, "A", "A",
"A", NA, NA, NA, NA, "A", NA, NA, NA, "A", NA, NA, NA, "A",
"A", "A", NA, NA, NA, NA, "A", NA, NA, NA, "A", NA, NA, NA,
"A", "A", "A", NA, NA, NA, NA, "A", NA, NA, NA, "A", NA,
NA, NA, "A", "A", "A", NA, NA, NA, NA, "A", NA, NA, NA, "A",
NA, NA, NA, "A", "A", "A", NA, NA, NA), X4 = c(NA, NA, "A",
NA, NA, NA, "A", NA, NA, "A", NA, NA, "A", "A", NA, NA, NA,
"A", NA, NA, NA, "A", NA, NA, "A", NA, NA, "A", "A", NA,
NA, NA, "A", NA, NA, NA, "A", NA, NA, "A", NA, NA, "A", "A",
NA, NA, NA, "A", NA, NA, NA, "A", NA, NA, "A", NA, NA, "A",
"A", NA, NA, NA, "A", NA, NA, NA, "A", NA, NA, "A", NA, NA,
"A", "A", NA, NA, NA, "A", NA, NA, NA, "A", NA, NA, "A",
NA, NA, "A", "A", NA), X5 = c(NA, NA, NA, "A", NA, NA, NA,
"A", NA, NA, "A", NA, "A", NA, "A", NA, NA, NA, "A", NA,
NA, NA, "A", NA, NA, "A", NA, "A", NA, "A", NA, NA, NA, "A",
NA, NA, NA, "A", NA, NA, "A", NA, "A", NA, "A", NA, NA, NA,
"A", NA, NA, NA, "A", NA, NA, "A", NA, "A", NA, "A", NA,
NA, NA, "A", NA, NA, NA, "A", NA, NA, "A", NA, "A", NA, "A",
NA, NA, NA, "A", NA, NA, NA, "A", NA, NA, "A", NA, "A", NA,
"A"), X6 = c(NA, NA, NA, NA, "A", NA, NA, NA, "A", NA, NA,
"A", NA, "A", "A", NA, NA, NA, NA, "A", NA, NA, NA, "A",
NA, NA, "A", NA, "A", "A", NA, NA, NA, NA, "A", NA, NA, NA,
"A", NA, NA, "A", NA, "A", "A", NA, NA, NA, NA, "A", NA,
NA, NA, "A", NA, NA, "A", NA, "A", "A", NA, NA, NA, NA, "A",
NA, NA, NA, "A", NA, NA, "A", NA, "A", "A", NA, NA, NA, NA,
"A", NA, NA, NA, "A", NA, NA, "A", NA, "A", "A")), .Names = c("X1",
"X2", "X3", "X4", "X5", "X6"), row.names = c(NA, -90L), class = "data.frame")
tmpCombs <- structure(c(1L, 1L, 1L, 2L, 2L, 3L, 2L, 3L, 4L, 3L, 4L, 4L), .Dim = c(6L,
2L))
res2 <- structure(list(X1 = c("A", "A", "A", "A", "A", "B", "B", "B",
"B", "B", "B", "B", "B", "B", "B", "A", "A", "A", "A", "A", "B",
"B", "B", "B", "B", "B", "B", "B", "B", "B", "A", "A", "A", "A",
"A", "B", "B", "B", "B", "B", "B", "B", "B", "B", "B", "A", "A",
"A", "A", "A", NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, "A", "A",
"A", "A", "A", NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, "A", "A",
"A", "A", "A", NA, NA, NA, NA, NA, NA, NA, NA, NA, NA), X2 = c("A",
"B", "B", "B", "B", "A", "A", "A", "A", "B", "B", "B", "B", "B",
"B", "A", "B", "B", "B", "B", "A", "A", "A", "A", NA, NA, NA,
NA, NA, NA, "A", "B", "B", "B", "B", "A", "A", "A", "A", NA,
NA, NA, NA, NA, NA, "A", NA, NA, NA, NA, "A", "A", "A", "A",
"B", "B", "B", "B", "B", "B", "A", NA, NA, NA, NA, "A", "A",
"A", "A", "B", "B", "B", "B", "B", "B", "A", NA, NA, NA, NA,
"A", "A", "A", "A", NA, NA, NA, NA, NA, NA), X3 = c("B", "A",
"B", "B", "B", "A", "B", "B", "B", "A", "A", "A", NA, NA, NA,
"B", "A", NA, NA, NA, "A", NA, NA, NA, "A", "A", "A", "B", "B",
"B", "B", "A", NA, NA, NA, "A", NA, NA, NA, "A", "A", "A", NA,
NA, NA, NA, "A", "B", "B", "B", "A", "B", "B", "B", "A", "A",
"A", "B", "B", "B", NA, "A", "B", "B", "B", "A", "B", "B", "B",
"A", "A", "A", NA, NA, NA, NA, "A", NA, NA, NA, "A", NA, NA,
NA, "A", "A", "A", "B", "B", "B"), X4 = c("B", "B", "A", NA,
NA, "B", "A", NA, NA, "A", NA, NA, "A", "A", NA, NA, NA, "A",
"B", "B", NA, "A", "B", "B", "A", "B", "B", "A", "A", NA, NA,
NA, "A", NA, NA, NA, "A", NA, NA, "A", NA, NA, "A", "A", "B",
"B", "B", "A", "B", "B", "B", "A", "B", "B", "A", "B", "B", "A",
"A", NA, "B", "B", "A", NA, NA, "B", "A", NA, NA, "A", NA, NA,
"A", "A", "B", NA, NA, "A", "B", "B", NA, "A", "B", "B", "A",
"B", "B", "A", "A", "B"), X5 = c(NA, NA, NA, "A", NA, NA, NA,
"A", NA, NA, "A", NA, "A", NA, "A", "B", "B", "B", "A", NA, "B",
"B", "A", NA, "B", "A", NA, "A", NA, "A", NA, NA, NA, "A", "B",
NA, NA, "A", "B", NA, "A", "B", "A", "B", "A", "B", "B", "B",
"A", NA, "B", "B", "A", NA, "B", "A", NA, "A", NA, "A", NA, NA,
NA, "A", "B", NA, NA, "A", "B", NA, "A", "B", "A", "B", "A",
"B", "B", "B", "A", "B", "B", "B", "A", "B", "B", "A", "B", "A",
"B", "A"), X6 = c(NA, NA, NA, NA, "A", NA, NA, NA, "A", NA, NA,
"A", NA, "A", "A", NA, NA, NA, NA, "A", NA, NA, NA, "A", NA,
NA, "A", NA, "A", "A", "B", "B", "B", "B", "A", "B", "B", "B",
"A", "B", "B", "A", "B", "A", "A", NA, NA, NA, NA, "A", NA, NA,
NA, "A", NA, NA, "A", NA, "A", "A", "B", "B", "B", "B", "A",
"B", "B", "B", "A", "B", "B", "A", "B", "A", "A", "B", "B", "B",
"B", "A", "B", "B", "B", "A", "B", "B", "A", "B", "A", "A")), .Names = c("X1",
"X2", "X3", "X4", "X5", "X6"), row.names = c(NA, -90L), class = "data.frame")
答案 0 :(得分:2)
tmpCombs
以获取每行的映射:
tc2 = tmpCombs[rep(seq_len(nrow(tmpCombs)),
each = nrow(res) %/% nrow(tmpCombs)), ]
dim(tc2)
#[1] 90 2
然后,仅在列上循环并计算NA
s的连续外观,在特定(根据tmpCombs
)增加的NA
数量出现时替换:
NAcounts = integer(nrow(res))
for(j in seq_along(res)) {
nas = is.na(res[[j]])
NAcounts = NAcounts + nas #`NA`s found so far in each row
#only for rows with `NA`s
#(no need for extended lookup if few rows contain `NA`)
#check if _this_ appearance of `NA` matches in `tmpCombs`
wnas = which(nas)
matches = NAcounts[wnas] == tc2[wnas, ]
res[[j]][wnas[as.logical(rowSums(matches))]] = "B"
}
identical(res, res2)
#[1] TRUE
答案 1 :(得分:1)
我认为它不会比你的循环解决方案好得多,但这里有一个可能的选择:
# Base R solution:
# note that res is a data.frame of characters but
# returned value will be a matrix of characters
toBind <-
lapply(1:nrow(tmpCombs),function(idx){
rowIdxs<- ((idx-1)*15+1):(idx*15)
replaceIdxs <- tmpCombs[idx,]
tmp <- apply(res[rowIdxs,],1,function(row){
row[na.omit(which(is.na(row))[replaceIdxs])] <- 'B'
return(row)
})
return(t(tmp))
})
fixed <- do.call(rbind,toBind)
N.B。
我建议您将res
转换为matrix
个字符,因为matrix
元素的访问速度通常比data.frame