【问题标题】:How to get the first and last non-Inf, non-NaN, non-NA, non-0 value from the variable?如何从变量中获取第一个和最后一个非Inf、非NaN、非NA、非0值?
【发布时间】:2020-10-23 01:00:54
【问题描述】:

这是我的玩具数据集:

    df <- tibble::tribble(
   ~data, ~first_non_0, ~last_non_0,
       0,         100,        430,
NA_real_,         100,        430,
     NaN,         100,        430,
     Inf,         100,        430,
     100,         100,        430,
     120,         100,        430,
     430,         100,        430,
     NaN,         100,        430,
     Inf,         100,        430,
       0,         100,        430,
NA_real_,         100,        430)

我想买

  1. 第一个非零、非 NA、非 NaN、非 Inf 值,如第 2 列所示
  2. 最后一个非零、非 NA、非 NaN、非 Inf 值,如第 3 列所示

this answer 的启发,我尝试了类似的方法,但不确定如何处理 NaN 和 Inf:

df %>% 
  mutate(first = na_if(data, 0) %>% 
           na_if(data, NaN) %>% 
           na_if(data, Inf) %>% 
           na.omit() %>% 
           dplyr::first(),
         last  = na_if(data, 0) %>% 
           na_if(data, NaN) %>% 
           na_if(data, Inf) %>% 
           na.omit() %>%
           dplyr::last())

【问题讨论】:

    标签: r dataframe tidyverse nan na


    【解决方案1】:

    如果你所有的值都是正数,你可以使用df$data &gt; 0作为条件然后你只需要处理Infinite,即

    i1 <- which(df$data > 0 & !is.infinite(df$data))
    
    df$data[i1[1]]
    #[1] 100
    df$data[i1[length(i1)]]
    #[1] 430
    

    如果您也有负值,您可以将条件从大于切换为不等于,(@markus 的赞美)

    i1 <- which(df$data != 0 & !is.infinite(df$data))
    

    【讨论】:

    • @markus 没有。诀窍是通过声明返回 TRUE、FALSE 或 NA 的 data &gt; 0 来完成。在无限的情况下,它返回 TRUE,因为 Inf &gt; 0,因此额外的 is.infinite 条件
    • 啊,我明白了。聪明的。如果OP也处理负值,也许将第一个检查更改为df$data != 0
    【解决方案2】:

    另一种选择:

    f <- function(x) {
      cond <- x != 0 & !is.na(x) & is.finite(x) & !is.nan(x)
      tmp <- x[cond]
      as.list(tmp[c(1, length(tmp))])
    }
    

    注意:该条件可以简化,参见@Sotos answer

    将函数应用于该列并将值作为新列插入

    df[, c("var1", "var2")] <- f(df$data)
    

    结果

    df
    # A tibble: 11 x 5
    #    data first_non_0 last_non_0  var1  var2
    #   <dbl>       <dbl>      <dbl> <dbl> <dbl>
    # 1     0         100        430   100   430
    # 2    NA         100        430   100   430
    # 3   NaN         100        430   100   430
    # 4   Inf         100        430   100   430
    # 5   100         100        430   100   430
    # 6   120         100        430   100   430
    # 7   430         100        430   100   430
    # 8   NaN         100        430   100   430
    # 9   Inf         100        430   100   430
    #10     0         100        430   100   430
    #11    NA         100        430   100   430
    

    【讨论】:

      【解决方案3】:

      从@Sotos 和@markus 使用的is.finite 以及他们的讨论中获取线索,我检查了这个并得到了答案。谢谢你们!

      is.finite(c(NA_real_, NaN, Inf))
      
      df %>% 
        mutate(first = na_if(data, 0),
               first = if_else(is.finite(first), first, NA_real_),
               first = first(na.omit(first))) %>% 
        mutate(last = na_if(data, 0),
               last = if_else(is.finite(last), last, NA_real_),
               last = last(na.omit(last)))
      

      结果:

      # A tibble: 11 x 5
          data first_non_0 last_non_0 first  last
         <dbl>       <int>      <int> <dbl> <dbl>
       1     0         100        430   100   430
       2    NA         100        430   100   430
       3   NaN         100        430   100   430
       4   Inf         100        430   100   430
       5   100         100        430   100   430
       6   120         100        430   100   430
       7   430         100        430   100   430
       8   NaN         100        430   100   430
       9   Inf         100        430   100   430
      10     0         100        430   100   430
      11    NA         100        430   100   430
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-01-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-04-19
        相关资源
        最近更新 更多