找到向量中的min但没有0

时间:2015-08-31 10:45:52

标签: r dplyr

我的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))

我想要做的是在min行中找到df但不是0 我做了

df<- df%>% rowwise() %>%
  do({
    th <- c(.$t1, .$t2, .$t3,)


    data.frame(., t_s_last = min(th[th > 0))
  })

但它可以工作但不适用于包含大于0的行的行。 如果行中只有0(第5行),如何返回0?

3 个答案:

答案 0 :(得分:4)

我们可以将applyif/else条件

一起使用
 apply(df, 1, function(x) if(all(x==0)) 0 else min(x[x> 0]))

或其他选项rowMins来自library(matrixStats)。我们将数据集中的“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

我们也可以使用if/else

中的do
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

答案 1 :(得分:4)

我猜测,因为您正在寻找零以上的值,所有值都是&gt; = 0和整数。因此,我们可以使用日志转换来将所有零转换为Inf,因此始终是最大的。这将有助于我们避免按行操作运行,而是使用max.col函数

的减号进行向量化
df[cbind(1:nrow(df), max.col(-abs(log(df))))]
## [1] 10 20  3  1  0

答案 2 :(得分:0)

以下是另一种使用dplyrtidyr的方法。比@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)