【问题标题】:Subtract rows with numeric values and ignore NAs用数值减去行并忽略 NA
【发布时间】:2019-11-06 11:54:48
【问题描述】:

我有几个包含 18 列的数据框,大约有 18 列。 50000 行。每个行条目代表特定站点(= 列)的测量值,数据包含 NA 值。

我需要减去每列的连续行(例如 row(i+1)-row(i))来检测阈值,但我需要忽略(并保留)NA,以便只有带有数字的条目值彼此相减。

我发现data.table 解决方案对于单列Iterate over a column ignoring but retaining NA values in R 和多列操作(例如Summarizing multiple columns with dplyr?)非常有用。

但是,我没有设法结合 SO 中建议的方法(即在多个列上应用 diff 并忽略 NA)

这是一个示例 df 用于说明和我尝试过的解决方案:

library(data.table)

df <- data.frame(x=c(1:3,NA,NA,9:7),y=c(NA,4:6, NA,15:13), z=c(6,2,7,14,20, NA, NA, 2))

这就是它对单个列的工作方式

 diff_x <- df[!is.na(x), lag_diff := x - shift(x)]  # actually what I want, but for more columns at once

这就是我如何使用lapply 在多个列上应用diff 函数

diff_all <- setDT(df)[,lapply(.SD, diff)]  # not exactly what I want because NAs are not ignored and  the difference between numeric values is not calculated 

非常感谢关于如何在第二行代码中实现有效的!is.na 或类似语句的任何建议(basedata.tabledplyr ......解决方案)。

【问题讨论】:

    标签: r data.table rows na subtraction


    【解决方案1】:

    定义一个辅助函数会让事情变得更简洁:

     lag_diff <- function(x) {
       which_nna <- which(!is.na(x))
       out <- rep(NA_integer_, length(x))
       out[which_nna] <- x[which_nna] - shift(x[which_nna])
       out
     }
    
    cols <- c("x", "y", "z")
    setDT(df)
    df[, paste0("lag_diff_", cols) := lapply(.SD, lag_diff), .SDcols = cols]
    

    结果:

    #     x  y  z lag_diff_x lag_diff_y lag_diff_z
    # 1:  1 NA  6         NA         NA         NA
    # 2:  2  4  2          1         NA         -4
    # 3:  3  5  7          1          1          5
    # 4: NA  6 14         NA          1          7
    # 5: NA NA 20         NA         NA          6
    # 6:  9 15 NA          6          9         NA
    # 7:  8 14 NA         -1         -1         NA
    # 8:  7 13  2         -1         -1        -18
    

    【讨论】:

      【解决方案2】:

      所以你正在寻找:

      library("data.table")
      
      df <- data.frame(x=c(1:3,NA,NA,9:7),y=c(NA,4:6, NA,15:13), z=c(6,2,7,14,20, NA, NA, 2))
      setDT(df)
      # diff_x <- df[!is.na(x), lag_diff := x - shift(x)]  # actually what I want, but
      
      lag_d <- function(x) { y <- x[!is.na(x)]; x[!is.na(x)] <- y - shift(y); x }
      df[, lapply(.SD, lag_d)]
      

      library("data.table")
      
      df <- data.frame(x=c(1:3,NA,NA,9:7),y=c(NA,4:6, NA,15:13), z=c(6,2,7,14,20, NA, NA, 2))
      lag_d <- function(x) { y <- x[!is.na(x)]; x[!is.na(x)] <- y - shift(y); x }
      as.data.frame(lapply(df, lag_d))
      

      【讨论】:

      • 非常感谢你们俩,jogo 和 @sindri_baldur,你们的快速回复和对我的问题非常有用的解决方案!
      猜你喜欢
      • 1970-01-01
      • 2018-04-24
      • 2020-07-04
      • 2020-08-11
      • 2017-10-25
      • 1970-01-01
      • 1970-01-01
      • 2021-06-30
      • 2013-10-16
      相关资源
      最近更新 更多