在 for 循环中使用 diff 函数

Using the diff function in a for loop

我有一个数据框,我想生成列,这些列在它之前的列之间存在差异。即有一个包含第 1 列 - 第 2 列的新列,接下来是第 2 列 - 第 3 列,等等。我已经写出代码(~伪代码?)但我不完全确定如何正确格式化它。这将成为不同文档的管道,因此我无法对列名或编号进行硬编码。我还希望此循环生成一个新列,其中 header 具有它减去的列的名称。

我的数据:

     Line_1    Line_2    Line_3    Line_4    Line_5    Line_6    Line_7
1         NA        NA        NA        NA        NA 0.0000000        NA
2  0.4054731 0.3193632 0.2667026 0.8494675 0.2394639 0.2936054 0.2453124
3  0.4048527 0.3195507 0.2693250 0.8664931 0.2380499 0.2931895 0.2437657
4  0.4041760 0.3226145 0.2731347 0.8756971 0.2338797 0.2876017 0.2432391
5  0.4079322 0.3264623 0.2750645 0.8770746 0.2273580 0.2866682 0.2476563

我的“代码”:

for (n in 1:ncol(tempDF2)) {
    sub <- diff(n, lag = 1, differences = 1)
    name <- paste0(n, " - ", n+1)
    tempDF2$name <- sub
}

我怎样才能让它工作?我也愿意申请 sapply 等循环的替代方案。

您可以使用 matrixStats 包中的 rowDiffs 并反转差异:

library(matrixStats)
df <- structure(list(Line_1 = c(NA, 0.4054731, 0.4048527, 0.404176, 
                                0.4079322), Line_2 = c(NA, 0.3193632, 0.3195507, 0.3226145, 0.3264623
                                ), Line_3 = c(NA, 0.2667026, 0.269325, 0.2731347, 0.2750645), 
                     Line_4 = c(NA, 0.8494675, 0.8664931, 0.8756971, 0.8770746
                     ), Line_5 = c(NA, 0.2394639, 0.2380499, 0.2338797, 0.227358
                     ), Line_6 = c(NA, 0.2936054, 0.2931895, 0.2876017, 0.2866682
                     ), Line_7 = c(0, 0.2453124, 0.2437657, 0.2432391, 0.2476563
                     )), class = "data.frame", row.names = c(NA, -5L))

-rowDiffs(as.matrix(df))
#>           [,1]      [,2]       [,3]      [,4]       [,5]      [,6]
#> [1,]        NA        NA         NA        NA         NA        NA
#> [2,] 0.0861099 0.0526606 -0.5827649 0.6100036 -0.0541415 0.0482930
#> [3,] 0.0853020 0.0502257 -0.5971681 0.6284432 -0.0551396 0.0494238
#> [4,] 0.0815615 0.0494798 -0.6025624 0.6418174 -0.0537220 0.0443626
#> [5,] 0.0814699 0.0513978 -0.6020101 0.6497166 -0.0593102 0.0390119

编辑:

如果与您的问题相反,您想要 Line_2 - Line_1 等的差异,那么它将是:

setNames(data.frame(rowDiffs(as.matrix(df))), 
         paste0(colnames(df)[-1], "-", colnames(df)[-ncol(df)]))
#>   Line_2-Line_1 Line_3-Line_2 Line_4-Line_3 Line_5-Line_4 Line_6-Line_5
#> 1            NA            NA            NA            NA            NA
#> 2    -0.0861099    -0.0526606     0.5827649    -0.6100036     0.0541415
#> 3    -0.0853020    -0.0502257     0.5971681    -0.6284432     0.0551396
#> 4    -0.0815615    -0.0494798     0.6025624    -0.6418174     0.0537220
#> 5    -0.0814699    -0.0513978     0.6020101    -0.6497166     0.0593102
#>   Line_7-Line_6
#> 1            NA
#> 2    -0.0482930
#> 3    -0.0494238
#> 4    -0.0443626
#> 5    -0.0390119

reprex package (v0.3.0)

于 2020-07-01 创建

不确定这是否正是您要查找的内容,但以下函数将按顺序计算第 1 列与第 n 列之间的差异。这显然只适用于具有数字列的数据框。您可以使用 dplyr 和动态变量命名(即 enquo())获得更多乐趣,但这可能会让您朝着正确的方向前进。

diff_cols <- function(dat) {
    list <- names(dat)
    col <- list()
    nam <- vector()
    for(i in 1:(ncol(dat)-1)) {
      col[[i]] <- dat[,i]-dat[,i+1] 
      nam[i] <- paste0(list[i], "-" ,list[i+1])
    }

  df <- as.data.frame(do.call(cbind, col))
  colnames(df) <- nam 
  return(df)
}
dat <- select_if(iris, is.numeric)
diff_cols(dat)

base R 中,我们可以通过取相同大小 data.frames 的差值(通过删除第一列和最后一列)

out <- tempDF2[-ncol(tempDF2)] - tempDF2[-1]
names(out) <- paste0(names(tempDF2)[-1], "-", names(tempDF2)[-ncol(tempDF2)]) 


out
#  Line_2-Line_1 Line_3-Line_2 Line_4-Line_3 Line_5-Line_4 Line_6-Line_5 Line_7-Line_6
#1            NA            NA            NA            NA            NA            NA
#2     0.0861099     0.0526606    -0.5827649     0.6100036    -0.0541415     0.0482930
#3     0.0853020     0.0502257    -0.5971681     0.6284432    -0.0551396     0.0494238
#4     0.0815615     0.0494798    -0.6025624     0.6418174    -0.0537220     0.0443626
#5     0.0814699     0.0513978    -0.6020101     0.6497166    -0.0593102     0.0390119

数据

tempDF2 <- structure(list(Line_1 = c(NA, 0.4054731, 0.4048527, 0.404176, 
0.4079322), Line_2 = c(NA, 0.3193632, 0.3195507, 0.3226145, 0.3264623
), Line_3 = c(NA, 0.2667026, 0.269325, 0.2731347, 0.2750645), 
    Line_4 = c(NA, 0.8494675, 0.8664931, 0.8756971, 0.8770746
    ), Line_5 = c(NA, 0.2394639, 0.2380499, 0.2338797, 0.227358
    ), Line_6 = c(NA, 0.2936054, 0.2931895, 0.2876017, 0.2866682
    ), Line_7 = c(0, 0.2453124, 0.2437657, 0.2432391, 0.2476563
    )), class = "data.frame", row.names = c(NA, -5L))