R中数据框或矩阵的列之间的lag-1差异

lag-1 difference between columns of a data frame or matrix in R

我想创建一个函数来计算 R 中多个列之间的 lag-1 差异。

例如,我的数据框如下所示:

  id  Value  Value2 Value3 Value4  
A234     10     15     NA     NA 
B345     20     25     25     30 
C500     20     25     15     NA

我想要函数计算第 5 列和第 4 列之间的差异。然后是第 4 和第 3 列,最后是第 3 和第 2 列。

我知道之前有两个关于行间差异的问答:

但我无法调整解决方案来处理列。对不起,如果这太简单了。我是 R 的新手。


df <- structure(list(id = c("A234", "B345", "C500"), Value = c(10L, 
20L, 20L), Value2 = c(15L, 25L, 25L), Value3 = c(NA, 25L, 15L
), Value4 = c(NA, 30L, NA)), .Names = c("id", "Value", "Value2", 
"Value3", "Value4"), class = "data.frame", row.names = c(NA, -3L))

没有测试这个但是,假设你的 data.frame 被称为 df 它可以像 cbind(df$Value2-df$Value,df$Value3-df$Value2,df$Value4-df$Value3) 你可以很容易地在函数中说唱。

数据框

I would like the function to take the difference between the 5th and 4th column. Then, the 4th and 3rd column and then last the 3rd and 2nd column.

我们可以做到

cbind(df[1], df[3:5] - df[2:4])
#    id Value2 Value3 Value4
#1 A234      5     NA     NA
#2 B345      5      0      5
#3 C500      5    -10     NA

df[3:5] - df[2:4] 之所以有效,是因为 element-wise 算术在 R 中是 well-defined 在两个相同大小的数据帧之间。特别是,DF1 - DF2 的列名将继承第一个数据框 DF1.

的列名

我们也可以使用负索引:

df0 <- df[-1]  ## drop "id" column
cbind(df[1], df0[-1] - df0[-length(df0)])
#    id Value2 Value3 Value4
#1 A234      5     NA     NA
#2 B345      5      0      5
#3 C500      5    -10     NA

警告:

由于一个dataframe可能会在不同的列中存储不同类型的数据,我建议你在尝试取差之前先检查它的列,否则算术运算可能无效。使用您的示例数据框,我们可以做到

sapply(df, class)
#         id       Value      Value2      Value3      Value4 
#"character"   "integer"   "integer"   "integer"   "integer" 

所以最后 4 列之间的差异是有效的。

这是 iris 数据集的另一个示例:

sapply(iris, class)
#Sepal.Length  Sepal.Width Petal.Length  Petal.Width      Species 
#   "numeric"    "numeric"    "numeric"    "numeric"     "factor" 

最后一列是 "factor",不能用于有效算术。

请注意,我们使用 class 而不是 mode 对每个数据框列进行类型检查,因为它会进行更全面的检查。有关更多说明,请参阅


矩阵

一个矩阵只能容纳一种类型的数据。使用 mode 检查数据类型以确保算法有效。例如,您不能对 "character" 数据进行算术运算。

假设我们有一个"numeric"矩阵

set.seed(0)
A <- round(matrix(runif(25), 5, 5), 2)
#     [,1] [,2] [,3] [,4] [,5]
#[1,] 0.90 0.20 0.06 0.77 0.78
#[2,] 0.27 0.90 0.21 0.50 0.93
#[3,] 0.37 0.94 0.18 0.72 0.21
#[4,] 0.57 0.66 0.69 0.99 0.65
#[5,] 0.91 0.63 0.38 0.38 0.13

mode(A)
#[1] "numeric"

我们可以使用以下方法来区分第 2 列和第 1 列、第 3 列和第 2 列等:

A[, -1, drop = FALSE] - A[, -ncol(A), drop = FALSE]
#      [,1]  [,2] [,3]  [,4]
#[1,] -0.70 -0.14 0.71  0.01
#[2,]  0.63 -0.69 0.29  0.43
#[3,]  0.57 -0.76 0.54 -0.51
#[4,]  0.09  0.03 0.30 -0.34
#[5,] -0.28 -0.25 0.00 -0.25

我认为对于您的目的,李哲元的回答是最简单和最优雅的。但是,我只是想展示您还可以如何使用我的 goto 函数解决这个问题,该函数用于包 Matrix 中的值 diff 之间的差异。在我的回答中,我保留了您要求的顺序(第 5 列 - 第 4 列,第 4 列 - 第 3 列等)。

# Load package
library(Matrix)    

# Create a dataframe of differences
cbind(df[1], rev(as.data.frame(t(apply(df[-1], 1, diff, 1)))))
#    id Value4 Value3 Value2
#1 A234     NA     NA      5
#2 B345      5      0      5
#3 C500     NA    -10      5