【问题标题】:Alternative to na.locf (zoo) for numbers数字的 na.locf (zoo) 的替代方案
【发布时间】:2019-08-09 03:49:57
【问题描述】:

我目前有一个相当复杂的数据集,但我试图将其分解并希望手头的问题能够足够复杂。

我的数据如下:

df <- data.frame(c(1,1,1,1,2,2,2,3,3,3), c(3,3,NA,5,0,0,0,7,4,7), 
                 c(TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE,
                   TRUE, FALSE))
colnames(df) <- c("ID", "Number", "Status")

> df
   ID Number Status
1   1      3   TRUE
2   1      3   TRUE
3   1     NA   TRUE
4   1      5  FALSE
5   2      0  FALSE
6   2      0  FALSE
7   2      0  FALSE
8   3      7  FALSE
9   3      4   TRUE
10  3      7  FALSE

我正在依次查看每个 ID(使用 dplyr group_by)。每当观察的状态为真时,我想用状态为假的后续数字替换“数字”。对于 ID = 1,这意味着所有 4 个观察值都为 5。

我找到了一种解决方法,但我确信一定有一个更简单的解决方案(使用替换?)。我是这样处理的:

library(dplyr)
library(zoo)

# Setting up a new variable that replaces all "unwanted
# numbers by NA
df$newNumber <- NA
df$newNumber[df$Status == FALSE] <- df$Number[df$Status == FALSE]

# Using the zoo function na.locf to replace the Gas
df <- df %>%
  group_by(ID) %>%
  mutate(Number2 = ifelse(any(Status == TRUE), na.locf(newNumber, 
fromLast = TRUE), Number2))

> df
# A tibble: 10 x 5
# Groups:   ID [3]
      ID Number Status newNumber Number2
   <dbl>  <dbl> <lgl>      <dbl>   <dbl>
 1     1      3 TRUE          NA       5
 2     1      3 TRUE          NA       5
 3     1     NA TRUE          NA       5
 4     1      5 FALSE          5       5
 5     2      0 FALSE          0       0
 6     2      0 FALSE          0       0
 7     2      0 FALSE          0       0
 8     3      7 FALSE          7       7
 9     3      4 TRUE          NA       7
10     3      7 FALSE          7       7

提前非常感谢您!

【问题讨论】:

    标签: r replace zoo locf


    【解决方案1】:

    tidyr::fill 的工作方式与zoo::na.locf 大致相同。

    library("tidyverse")
    
    df <- data.frame(c(1,1,1,1,2,2,2,3,3,3), c(3,3,NA,5,0,0,0,7,4,7),
                     c(TRUE, TRUE, TRUE, FALSE, FALSE, FALSE, FALSE, FALSE,
                       TRUE, FALSE))
    colnames(df) <- c("ID", "Number", "Status")
    
    df %>%
      mutate(Number2 = if_else(Status, NA_real_, Number)) %>%
      group_by(ID) %>%
      fill(Number2, .direction = "up")
    #> # A tibble: 10 x 4
    #> # Groups:   ID [3]
    #>       ID Number Status Number2
    #>    <dbl>  <dbl> <lgl>    <dbl>
    #>  1     1      3 TRUE         5
    #>  2     1      3 TRUE         5
    #>  3     1     NA TRUE         5
    #>  4     1      5 FALSE        5
    #>  5     2      0 FALSE        0
    #>  6     2      0 FALSE        0
    #>  7     2      0 FALSE        0
    #>  8     3      7 FALSE        7
    #>  9     3      4 TRUE         7
    #> 10     3      7 FALSE        7
    

    reprex package (v0.2.1) 于 2019-03-18 创建

    【讨论】:

      【解决方案2】:

      你可以这样做:

      library(zoo)
      df$Number[df$Status==TRUE] <- NA #replace Number with NA for all Status = TRUE
      df$Number <- na.locf(df$Number, fromLast = TRUE) 
      
         ID Number Status
      1   1      5   TRUE
      2   1      5   TRUE
      3   1      5   TRUE
      4   1      5  FALSE
      5   2      0  FALSE
      6   2      0  FALSE
      7   2      0  FALSE
      8   3      7  FALSE
      9   3      7   TRUE
      10  3      7  FALSE
      

      Data.table 解决方案

      library(data.table)
      setDT(df)
      df[Status==TRUE, Number:=NA_real_]
      df[,Number:=na.locf(Number, fromLast=TRUE, na.rm = FALSE)]
      

      【讨论】:

        猜你喜欢
        • 2023-03-20
        • 2019-02-18
        • 1970-01-01
        • 2013-04-24
        • 1970-01-01
        • 1970-01-01
        • 2014-03-08
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多