我的df是这样的
df <- data.frame(t1 = c(10, 20, 30, 1, 0), t2 = c(30, 0, 40, 0, 0), t3 = c(10, 0, 3, 10, 0))
我要做的是在df
行中找到min
,但不是0我做
df<- df%>% rowwise() %>%
do({
th <- c(.$t1, .$t2, .$t3,)
data.frame(., t_s_last = min(th[th > 0))
})
,但它的工作,但不是为包含STH大于0的行。如果行(第5行)中只有0,如何使此返回0 ?
我们可以在if/else
条件下使用apply
apply(df, 1, function(x) if(all(x==0)) 0 else min(x[x> 0]))
或者另一个选项是library(matrixStats)
中的rowMins
。我们将数据集中的'0'值替换为NA
,将rowMins
替换为na.rm=TRUE
,并将'Inf'值替换为0。
library(matrixStats)
is.na(df) <- df==0
v1 <- rowMins(as.matrix(df), na.rm=TRUE)
v1[is.infinite(v1)] <- 0
v1
#[1] 10 20 3 1 0
我们也可以在do
if/else
library(dplyr)
df %>%
rowwise() %>%
do({th <- unlist(.[.>0])
data.frame(., t_s_last = if(all(th==0)) 0 else min(th))})
# t1 t2 t3 t_s_last
#1 10 30 10 10
#2 20 0 0 20
#3 30 40 3 3
#4 1 0 10 1
#5 0 0 0 0
我猜,因为你正在寻找高于零的值,所有的值>=0和整数。因此,我们可以使用log变换,以便将所有的0转换为Inf
,从而始终是最大的。这将帮助我们避免逐行操作,而是使用max.col
函数
df[cbind(1:nrow(df), max.col(-abs(log(df))))]
## [1] 10 20 3 1 0
这里是使用dplyr
和tidyr
的另一种方法。比@akrun的回答长一点。但如果不使用do
:
library(dplyr)
library(tidyr)
df %>%
mutate(id = row_number()) %>%
gather(time, value, t1:t3) %>%
group_by(id) %>%
mutate(ts = ifelse(all(value == 0), 0, min(value[value != 0]))) %>%
spread(time, value)