重复从第 1 行减去第 2 行

Subtracting row 2 from row 1 repeatedly

我想在 R 中创建我的数据集中的一列,我从第 1 行减去第 2 行,从第 3 行减去第 4 行,依此类推。此外,我希望对每一行重复减法结果(e.g.if 减法 row2-row1 的结果是 -0.294803,我希望这个值同时出现在 row1 和 row2 中,因此对这两个因素重复两次减法,等等所有减法)。

这是我的数据集。

我尝试使用聚合函数,但没有成功。 有什么提示吗?

解决方案 1

一种方法是使用一个简单的循环:

(download mydata.csv)

a = read.table("mydata.csv",header=T,sep=";")
a$delta= NA
for(i in seq(1, nrow(a), by=2 )){
  a[i,"delta"] = a[i+1,"delta"] = a[i+1,"log"] - a[i,"log"]
}

这里发生的事情是 for 循环迭代每个奇数(这就是 seq(...,by=2) 所做的。所以对于第一行、第三行、第五行等,我们分配到那一行和下一行计算出的差异。 returns:

> a
   su    match  log delta
1   1    match 5.80  0.30
2   1 mismatch 6.10  0.30
3   2    match 6.09 -0.04
4   2 mismatch 6.05 -0.04
5   3    match 6.42 -0.12
6   3 mismatch 6.30 -0.12
7   4    match 6.20 -0.20
8   4 mismatch 6.00 -0.20
9   5    match 5.90  0.19
10  5 mismatch 6.09  0.19

解决方案 2

如果您有大量数据,这种方法可能会很慢。通常 R 与 apply 家族apply 的另一种形式的迭代函数配合使用效果更好。

上面相同的代码可以这样优化:

a$delta = rep(
             sapply(seq(1, nrow(a), by=2 ),
                 function(i){ a[i+1,"log"] - a[i,"log"] }
             ),
          each=2)

给出与第一个解决方案完全相同的结果,应该更快,但也不太直观。


解决方案 3

最后,在我看来,鉴于您的数据类型,您正试图通过使用 long 数据帧格式来使用复杂的方法。 我会将其重塑为 wide,然后使用单独的列进行更符合逻辑的操作,而不需要重复数据。

像这样:

a = read.table("mydata.csv",header=T,sep=";")
a = reshape(a, idvar = "su", timevar = "match", direction = "wide")
#now creating what you want became a very simple thing:
a$delta = a[[3]]-a[[2]]

哪个returns:

>a
   su log.match log.mismatch delta
1  1      5.80         6.10  0.30
3  2      6.09         6.05 -0.04
5  3      6.42         6.30 -0.12
7  4      6.20         6.00 -0.20
9  5      5.90         6.09  0.19

增量列包含您需要的值。如果您真的需要长格式进行进一步分析,您可以随时返回:

a= reshape(a, idvar = "su", timevar = "match", direction = "long")
#sort to original order:
a = a[with(a, order(su)), ]

另一个可能的解决方案是:

x <- read.table("mydata.csv",header=T,sep=";")
x$diff <- rep(x$log[seq(2,nrow(x),by=2)] - x$log[seq(1,nrow(x),by=2)], each=2)

通过使用函数 seq(),您可以生成行位置序列:

1, 3, 5, ... 9

2, 4, 6, ... 10

之后,代码将第 2...10 行减去第 1...9 行。使用命令 rep() 复制每个结果,并将其分配给新列 diff。