我试图为数据框中的每一行找到第一个非True(减1)。
结果如下:
V1 V2 V3 V4 V5 true
1 TRUE FALSE FALSE TRUE FALSE 1
2 TRUE FALSE FALSE FALSE NA 1
3 FALSE FALSE FALSE FALSE TRUE 0
4 FALSE FALSE FALSE FALSE FALSE 0
5 FALSE FALSE FALSE FALSE FALSE 0
6 FALSE FALSE FALSE FALSE FALSE 0
以下代码有效,但由于循环而耗时太长。我不确定如何使用apply语句正确执行此操作。
#Create the function to find the first non-true
min.true <- function(x,i){
min(which(x[i,]==!TRUE))-1
}
#Create a null column
match.words$true <- NA
#Find the first non true in each row
for (i in 1:nrow(match.words)){
match.words$true[i] <- min.true(match.words,i)
}
基本上我正在寻找能够跑得更快的这样的事情
match.words$true <- apply(match.words, 1, min.true(match.words))
谢谢,
答案 0 :(得分:4)
基础R中的一个简单变体:
match.words$true <- apply(match.words, 1, which.min) - 1
功能which.min(x)
返回向量x
中的最小值索引,或者在逻辑向量的情况下,返回第一个FALSE
值的索引。这在?which.min
的帮助页面中进行了描述:
Min()或Max()在哪里或第一个为TRUE或FALSE?
描述
确定位置,即数字(或逻辑)向量的(第一个)最小值或最大值的索引。
因此which.min()
的输出正是我们在这种情况下所需要的。剩下要做的就是将其包含到带有边距1的apply()
中以获取每行的索引,并按照问题陈述中的要求减去1
。
修改强>
如果data.frame保留所有值为TRUE
的行,则会出现一种特殊情况。然后,which.min()
返回这些行的第一个索引,这可能不合适。由于未找到FALSE
值,因此最好返回NA
。如果出现这种情况,可以在创建match.words $ true column:
NArows <- which(apply(df1, 1, all))
match.words$true <- apply(match.words, 1, which.min) - 1
match.words$true[NArows] <- NA
答案 1 :(得分:2)
像你这样的一些数据:
t <- matrix(c(TRUE, FALSE, FALSE, TRUE, FALSE, TRUE, FALSE,
FALSE, FALSE, NA), nrow=2)
t
# [,1] [,2] [,3] [,4] [,5]
# [1,] TRUE FALSE FALSE FALSE FALSE
# [2,] FALSE TRUE TRUE FALSE NA
略微修改功能:
min.true <- function(x){
min(which(x==!TRUE))-1
}
在一行测试:
min.true(t[1,])
# [1] 1
将其应用于每一行:
apply(t, 1, min.true)
# [1] 1 0
答案 2 :(得分:2)
?max.col
可以适应在这里工作,这应该相对较快。为简单起见,将@ TARehman的data_mat
重命名为mat
:
tmp <- replace(!mat, is.na(mat), FALSE)
replace(max.col(tmp,"first")-1, rowSums(tmp)==0, NA)
#[1] 1 1 0 NA 0 0 NA 3
答案 3 :(得分:1)
你可以试试这个:
match.words$true = apply(match.words,MARGIN = 1,function(t){return(min(which(t!=T))-1)})
答案 4 :(得分:1)
这是一个使用不同机制rle
功能的选项。它的好处是几乎不需要输入消毒。
data_mat <- matrix(c(TRUE, FALSE, FALSE, TRUE, TRUE,
TRUE, FALSE, FALSE, FALSE, NA,
FALSE, FALSE, TRUE, FALSE, FALSE,
TRUE, TRUE, TRUE, TRUE, TRUE,
FALSE, TRUE, TRUE, TRUE, TRUE,
FALSE, FALSE, FALSE, FALSE, FALSE,
NA, NA, NA, NA, NA,
NA, NA, TRUE, FALSE, TRUE), nrow=8, byrow = TRUE)
func_first_nontrue_row <- function(input_row) {
row <- rle(input_row)
first_nontrue <- head(x = head(x = cumsum(c(1,row$lengths)),n = -1)[which(!row$values)],
n = 1) - 1
if(length(first_nontrue) == 0) {return(-99)} else {return(first_nontrue)}
}
output <- apply(X = data_mat,MARGIN = 1,FUN = func_first_true_row)
output
## [1] 1 1 0 -99 0 0 -99 3
编辑修改和解释:
rle
函数创建一个对象,该对象对向量中的数据运行长度进行编码(因此rle
用于运行长度编码)。
通过获取由1和lengths
(起始点加上每个项目的长度)组成的向量的累积和,然后删除最后一个元素,您将获得每次运行的起始位置。使用values
参数,您可以将该向量子集化为仅FALSE语句。因此,调用head()
抓取第一个,并事先调用head()
以删除最后一个元素。我对它进行了清理,以便通过检查输出的长度是否为0来检查没有FALSE语句的行。您可以根据需要调整它。
速度方面,我不确定这会比其他解决方案更好,但它总是能产生一些东西,因为rle
调用将始终创建实际值,即使是整个NAs向量。