我有一个数据框,看起来像这样;
df <- data.frame(Trip =c(rep("A",10),rep("B",10)),
State =c(0,0,0,1,1,1,0,0,1,0,0,1,1,0,0,0,1,1,1,0),
Distance = c(0,2,9,4,3,1,4,5,6,3,2,6,1,5,3,3,6,1,8,2),
DistanceToNext = c(NA,NA,NA,3,1,15,NA,NA,NA,NA,NA,1,17,NA,NA,NA,1,8,NA,NA))
Trip State Distance DistanceToNext
1 A 0 1 NA
2 A 0 2 NA
3 A 0 9 NA
4 A 1 4 3
5 A 1 3 1
6 A 1 1 15
7 A 0 4 NA
8 A 0 5 NA
9 A 1 6 NA
10 A 0 3 NA
11 B 0 2 NA
12 B 1 6 1
13 B 1 1 17
14 B 0 5 NA
15 B 0 3 NA
16 B 0 3 NA
17 B 1 6 1
18 B 1 1 8
19 B 1 8 NA
20 B 0 2 NA状态列指示捕鱼船是在钓鱼(状态= 1)还是不在钓鱼(状态= 0)。我想计算每个钓鱼事件之间的距离(State = 1)。
距离列表示该行位置与前一行之间的距离(例如,它是滞后距离)。
DistanceToNext列是我试图生成的答案,对于Trip中的所有行,它都应该是NA,直到钓鱼状态= 1的第一行。对于此行,DistanceToNext应该等于后续行的距离列的总和,直到下一个钓鱼状态= 1。
例如,第4行是行程A中的第一个钓鱼事件(状态= 1),DistanceToNext单元格应该是下一个钓鱼事件之前行进的距离,在他的情况下是距离为3的下一行(第5行)。
对于第5行,下一个钓鱼事件再次是下一行(第6行),距离为1。但是,对于第6行,我们看到直到第9行才有另一个钓鱼事件,所以我需要6和9之间的行的d列的累积和为15。
如果它是它的x分组(A或B)中的最后一行State =1,那么就没有另一个钓鱼事件,所以没有要计算的距离,所以我希望它给出NA。
发布于 2021-08-04 16:56:26
在base R中,你可以这样做:
fun <- function(df){
a <- which(df$State == 1)
b <- rep(NA, nrow(df))
d <- mapply(function(x, y) sum(df$Distance[(x+1):y]), head(a,-1), tail(a, -1))
b[a] <- c(d, NA)
transform(df, DisttoNext = b)
}
do.call(rbind, by(df, df$Trip, fun))
Trip State Distance DistanceToNext DisttoNext
A.1 A 0 0 NA NA
A.2 A 0 2 NA NA
A.3 A 0 9 NA NA
A.4 A 1 4 3 3
A.5 A 1 3 1 1
A.6 A 1 1 15 15
A.7 A 0 4 NA NA
A.8 A 0 5 NA NA
A.9 A 1 6 NA NA
A.10 A 0 3 NA NA
B.11 B 0 2 NA NA
B.12 B 1 6 1 1
B.13 B 1 1 17 17
B.14 B 0 5 NA NA
B.15 B 0 3 NA NA
B.16 B 0 3 NA NA
B.17 B 1 6 1 1
B.18 B 1 1 8 8
B.19 B 1 8 NA NA
B.20 B 0 2 NA NA发布于 2021-08-05 06:10:54
这是另一个你可以使用的解决方案。我还对每个组中的每个State/ Distance向量使用了一个自定义函数,以产生所需的输出:
fn <- function(State, Distance) {
out <- rep(NA, length(State))
inds <- which(State == 1)
for(i in inds) {
if(State[i] == 1 & State[i + 1] == 1) {
out[i] <- Distance[i + 1]
} else if (State[i] == 1 & State[i + 1] == 0 & i != inds[length(inds)]) {
nx <- which(inds == i)
out[i] <- sum(Distance[(i+1):(inds[nx + 1])])
} else {
NA
}
}
out
}
df %>%
group_by(Trip) %>%
mutate(MyDistance = fn(State, Distance))
# A tibble: 20 x 5
# Groups: Trip [2]
Trip State Distance DistanceToNext MyDistance
<chr> <dbl> <dbl> <dbl> <dbl>
1 A 0 0 NA NA
2 A 0 2 NA NA
3 A 0 9 NA NA
4 A 1 4 3 3
5 A 1 3 1 1
6 A 1 1 15 15
7 A 0 4 NA NA
8 A 0 5 NA NA
9 A 1 6 NA NA
10 A 0 3 NA NA
11 B 0 2 NA NA
12 B 1 6 1 1
13 B 1 1 17 17
14 B 0 5 NA NA
15 B 0 3 NA NA
16 B 0 3 NA NA
17 B 1 6 1 1
18 B 1 1 8 8
19 B 1 8 NA NA
20 B 0 2 NA NA发布于 2021-08-05 18:05:44
data.table替代方案。
library(data.table)
setDT(df)
df[,`:=`(next_dist = shift(Distance, type = "lead"), g = cumsum(State), ri = .I),
by = Trip]
d = df[ , .(ri = ri[1], State = State[1], s = sum(next_dist)), by = .(Trip, g)]
df[d[State == 1, .SD[-.N], by = Trip], on = .(ri), s := s]
df[ , `:=`(ri = NULL, next_dist = NULL, g = NULL)]
# Trip State Distance DistanceToNext s
# 1: A 0 0 NA NA
# 2: A 0 2 NA NA
# 3: A 0 9 NA NA
# 4: A 1 4 3 3
# 5: A 1 3 1 1
# 6: A 1 1 15 15
# 7: A 0 4 NA NA
# 8: A 0 5 NA NA
# 9: A 1 6 NA NA
# 10: A 0 3 NA NA
# 11: B 0 2 NA NA
# 12: B 1 6 1 1
# 13: B 1 1 17 17
# 14: B 0 5 NA NA
# 15: B 0 3 NA NA
# 16: B 0 3 NA NA
# 17: B 1 6 1 1
# 18: B 1 1 8 8
# 19: B 1 8 NA NA
# 20: B 0 2 NA NA解释:
将数据转换为data.table (setDT(df))。
对于每个'Trip‘(by = Trip),通过引用创建新的变量(:=):next distance (shift(Distance, type = "lead")),一个分组变量,它在每次'State’为1时增加(cumsum(State)),一个用于连接结果的行索引(.I;这也可以先完成,不需要分组)。
对于每个'Trip‘和'State group’(by = .(Trip, g)),选择first row index (ri[1]),first 'State‘(State = State[1]),并对引线距离(sum(next_dist))求和。
从上面的结果中,选择“状态”为1 (State == 1)的行。然后,对于每个'Trip‘(by = Trip),选择除最后一行(-.N)之外的数据子集(.SD)。连接到行索引(on = .(ri))上的原始数据。创建一个新列,sum of distances,'s‘by reference (:=)。如果需要,可以删除temp变量。
https://stackoverflow.com/questions/68653741
复制相似问题