如何识别条件特定边界内的行并计算差异?
How to identify rows within a certain boundary of a condition and calculate the differences?
假设我有以下数据集:
> dat
value id
1: 2.785300 1
2: 4.164371 1
3: 4.179532 1
4: 4.373546 1
5: 4.378759 1
6: 4.694612 1
7: 4.955066 2
8: 4.983810 2
9: 5.183643 2
10: 5.329508 2
11: 5.389843 2
12: 5.487429 2
13: 5.575781 3
14: 5.738325 3
15: 5.943836 3
16: 6.124931 3
17: 6.511781 3
18: 6.595281 3
可通过以下方式创建:
set.seed(1)
library(data.table)
dat <- data.table(value=round(rnorm(18, mean = 5, sd = 1),6))[order(value)][,id:=rep(1:3, each=6)]
接下来我做的是创建一个变量,它指示新的 id
首先出现在哪一行,并为该行指定一个特定的 changeid
,所有其他行的 NA 值为:
dat[, changeid:=ifelse(+(!(id==shift(id,n=1L,type="lag")))==1,1,NA)
][, changeid:=rleid(changeid)[changeid==1]]
给出:
> dat
value id changeid
1: 2.785300 1 NA
2: 4.164371 1 NA
3: 4.179532 1 NA
4: 4.373546 1 NA
5: 4.378759 1 NA
6: 4.694612 1 NA
7: 4.955066 2 2
8: 4.983810 2 NA
9: 5.183643 2 NA
10: 5.329508 2 NA
11: 5.389843 2 NA
12: 5.487429 2 NA
13: 5.575781 3 4
14: 5.738325 3 NA
15: 5.943836 3 NA
16: 6.124931 3 NA
17: 6.511781 3 NA
18: 6.595281 3 NA
现在我想创建两个新变量:
- 一个名为
window
的变量,在 value
的某个边界内(例如:在具有changeid
值)。其他行有 NA
。
- 一个名为
iddif
的变量,与具有 changeid
的行的 value
不同。其他行有 NA
。
想要的结果:
> dat
value id changeid window iddif
1: 2.785300 1 NA NA NA
2: 4.164371 1 NA NA NA
3: 4.179532 1 NA NA NA
4: 4.373546 1 NA NA NA
5: 4.378759 1 NA NA NA
6: 4.694612 1 NA NA NA
7: 4.955066 2 2 2 0.000000
8: 4.983810 2 NA 2 0.028744
9: 5.183643 2 NA NA NA
10: 5.329508 2 NA NA NA
11: 5.389843 2 NA 4 -0.185938
12: 5.487429 2 NA 4 -0.088352
13: 5.575781 3 4 4 0.000000
14: 5.738325 3 NA 4 0.162544
15: 5.943836 3 NA NA NA
16: 6.124931 3 NA NA NA
17: 6.511781 3 NA NA NA
18: 6.595281 3 NA NA NA
有什么想法可以达到这个预期的结果吗?
附加问题:如何让 changeid
从 1
开始,然后随着 1
递增以用于下一次 ID 更改?
如果解决方案也使用 data.table
就好了。
这是一个可能的解决方案,使用 foverlaps
首先,我将创建 changeid
如下(根据奖金)
dat[c(0L, diff(id)) == 1L, changeid := 1:.N]
然后,我将创建一个临时数据集,其中 changeid
不是 NA
,键入它,在 dat
和 运行 [=12] 中创建间隔列=] 在他们之上。然后,提取匹配的行并更新原始数据
temp <- dat[!is.na(changeid), .(start = value, end = value)] # temp data
dat[, `:=`(start = value - 0.2, end = value + 0.2)] # set boundries
setkey(temp) # key the smaller data
res <- foverlaps(dat, temp, which = TRUE, nomatch = 0L) # get matched incidents
dat[res$xid, `:=`(window = res$yid, iddif = temp$start[res$yid])] # update values
dat[!is.na(window), iddif := value - iddif] # calculate differences
dat
# value id changeid start end window iddif
# 1: 2.785300 1 NA 2.585300 2.985300 NA NA
# 2: 4.164371 1 NA 3.964371 4.364371 NA NA
# 3: 4.179532 1 NA 3.979532 4.379532 NA NA
# 4: 4.373546 1 NA 4.173546 4.573546 NA NA
# 5: 4.378759 1 NA 4.178759 4.578759 NA NA
# 6: 4.694612 1 NA 4.494612 4.894612 NA NA
# 7: 4.955066 2 1 4.755066 5.155066 1 0.000000
# 8: 4.983810 2 NA 4.783810 5.183810 1 0.028744
# 9: 5.183643 2 NA 4.983643 5.383643 NA NA
# 10: 5.329508 2 NA 5.129508 5.529508 NA NA
# 11: 5.389843 2 NA 5.189843 5.589843 2 -0.185938
# 12: 5.487429 2 NA 5.287429 5.687429 2 -0.088352
# 13: 5.575781 3 2 5.375781 5.775781 2 0.000000
# 14: 5.738325 3 NA 5.538325 5.938325 2 0.162544
# 15: 5.943836 3 NA 5.743836 6.143836 NA NA
# 16: 6.124931 3 NA 5.924931 6.324931 NA NA
# 17: 6.511781 3 NA 6.311781 6.711781 NA NA
# 18: 6.595281 3 NA 6.395281 6.795281 NA NA
(如果不喜欢可以删除 start
和 end
)
假设我有以下数据集:
> dat
value id
1: 2.785300 1
2: 4.164371 1
3: 4.179532 1
4: 4.373546 1
5: 4.378759 1
6: 4.694612 1
7: 4.955066 2
8: 4.983810 2
9: 5.183643 2
10: 5.329508 2
11: 5.389843 2
12: 5.487429 2
13: 5.575781 3
14: 5.738325 3
15: 5.943836 3
16: 6.124931 3
17: 6.511781 3
18: 6.595281 3
可通过以下方式创建:
set.seed(1)
library(data.table)
dat <- data.table(value=round(rnorm(18, mean = 5, sd = 1),6))[order(value)][,id:=rep(1:3, each=6)]
接下来我做的是创建一个变量,它指示新的 id
首先出现在哪一行,并为该行指定一个特定的 changeid
,所有其他行的 NA 值为:
dat[, changeid:=ifelse(+(!(id==shift(id,n=1L,type="lag")))==1,1,NA)
][, changeid:=rleid(changeid)[changeid==1]]
给出:
> dat
value id changeid
1: 2.785300 1 NA
2: 4.164371 1 NA
3: 4.179532 1 NA
4: 4.373546 1 NA
5: 4.378759 1 NA
6: 4.694612 1 NA
7: 4.955066 2 2
8: 4.983810 2 NA
9: 5.183643 2 NA
10: 5.329508 2 NA
11: 5.389843 2 NA
12: 5.487429 2 NA
13: 5.575781 3 4
14: 5.738325 3 NA
15: 5.943836 3 NA
16: 6.124931 3 NA
17: 6.511781 3 NA
18: 6.595281 3 NA
现在我想创建两个新变量:
- 一个名为
window
的变量,在value
的某个边界内(例如:在具有changeid
值)。其他行有NA
。 - 一个名为
iddif
的变量,与具有changeid
的行的value
不同。其他行有NA
。
想要的结果:
> dat
value id changeid window iddif
1: 2.785300 1 NA NA NA
2: 4.164371 1 NA NA NA
3: 4.179532 1 NA NA NA
4: 4.373546 1 NA NA NA
5: 4.378759 1 NA NA NA
6: 4.694612 1 NA NA NA
7: 4.955066 2 2 2 0.000000
8: 4.983810 2 NA 2 0.028744
9: 5.183643 2 NA NA NA
10: 5.329508 2 NA NA NA
11: 5.389843 2 NA 4 -0.185938
12: 5.487429 2 NA 4 -0.088352
13: 5.575781 3 4 4 0.000000
14: 5.738325 3 NA 4 0.162544
15: 5.943836 3 NA NA NA
16: 6.124931 3 NA NA NA
17: 6.511781 3 NA NA NA
18: 6.595281 3 NA NA NA
有什么想法可以达到这个预期的结果吗?
附加问题:如何让 changeid
从 1
开始,然后随着 1
递增以用于下一次 ID 更改?
如果解决方案也使用 data.table
就好了。
这是一个可能的解决方案,使用 foverlaps
首先,我将创建 changeid
如下(根据奖金)
dat[c(0L, diff(id)) == 1L, changeid := 1:.N]
然后,我将创建一个临时数据集,其中 changeid
不是 NA
,键入它,在 dat
和 运行 [=12] 中创建间隔列=] 在他们之上。然后,提取匹配的行并更新原始数据
temp <- dat[!is.na(changeid), .(start = value, end = value)] # temp data
dat[, `:=`(start = value - 0.2, end = value + 0.2)] # set boundries
setkey(temp) # key the smaller data
res <- foverlaps(dat, temp, which = TRUE, nomatch = 0L) # get matched incidents
dat[res$xid, `:=`(window = res$yid, iddif = temp$start[res$yid])] # update values
dat[!is.na(window), iddif := value - iddif] # calculate differences
dat
# value id changeid start end window iddif
# 1: 2.785300 1 NA 2.585300 2.985300 NA NA
# 2: 4.164371 1 NA 3.964371 4.364371 NA NA
# 3: 4.179532 1 NA 3.979532 4.379532 NA NA
# 4: 4.373546 1 NA 4.173546 4.573546 NA NA
# 5: 4.378759 1 NA 4.178759 4.578759 NA NA
# 6: 4.694612 1 NA 4.494612 4.894612 NA NA
# 7: 4.955066 2 1 4.755066 5.155066 1 0.000000
# 8: 4.983810 2 NA 4.783810 5.183810 1 0.028744
# 9: 5.183643 2 NA 4.983643 5.383643 NA NA
# 10: 5.329508 2 NA 5.129508 5.529508 NA NA
# 11: 5.389843 2 NA 5.189843 5.589843 2 -0.185938
# 12: 5.487429 2 NA 5.287429 5.687429 2 -0.088352
# 13: 5.575781 3 2 5.375781 5.775781 2 0.000000
# 14: 5.738325 3 NA 5.538325 5.938325 2 0.162544
# 15: 5.943836 3 NA 5.743836 6.143836 NA NA
# 16: 6.124931 3 NA 5.924931 6.324931 NA NA
# 17: 6.511781 3 NA 6.311781 6.711781 NA NA
# 18: 6.595281 3 NA 6.395281 6.795281 NA NA
(如果不喜欢可以删除 start
和 end
)