重复从第 1 行减去第 2 行
Subtracting row 2 from row 1 repeatedly
我想在 R 中创建我的数据集中的一列,我从第 1 行减去第 2 行,从第 3 行减去第 4 行,依此类推。此外,我希望对每一行重复减法结果(e.g.if 减法 row2-row1 的结果是 -0.294803,我希望这个值同时出现在 row1 和 row2 中,因此对这两个因素重复两次减法,等等所有减法)。
这是我的数据集。
我尝试使用聚合函数,但没有成功。
有什么提示吗?
解决方案 1
一种方法是使用一个简单的循环:
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。
我想在 R 中创建我的数据集中的一列,我从第 1 行减去第 2 行,从第 3 行减去第 4 行,依此类推。此外,我希望对每一行重复减法结果(e.g.if 减法 row2-row1 的结果是 -0.294803,我希望这个值同时出现在 row1 和 row2 中,因此对这两个因素重复两次减法,等等所有减法)。
这是我的数据集。
我尝试使用聚合函数,但没有成功。 有什么提示吗?
解决方案 1
一种方法是使用一个简单的循环:
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。