我有一个由3个部分组成的A部分.首先,我描述了我成功地做了什么,然后我是如何不成功的更多的部分。
节的长度为 data.table
d1
.
library(data.table)
d1 <- data.table(
Part="A",
Section=1:3,
SecLen=c(10,30,9))
d1
# Part Section SecLen
# 1: A 1 10
# 2: A 2 30
# 3: A 3 9
我也有一套沿部分的位置,在。d2
.
d2 <- data.table(
Part="A",
PartLoc=c(0,7.5,10,20,35,45,49))
d2
# Part PartLoc
# 1: A 0.0
# 2: A 7.5
# 3: A 10.0
# 4: A 20.0
# 5: A 35.0
# 6: A 45.0
# 7: A 49.0
我想添加每个位置所在的节。
首先,我将章节长度堆叠在 d1
使用 cumsum
d1[,CumLen:=cumsum(SecLen)]
d1
# Part Section SecLen CumLen
# 1: A 1 10 10
# 2: A 2 30 40
# 3: A 3 9 49
那我就用 findInterval
来映射该部分。请注意,我希望位置10被分配到第1节,而不是第2节。
d2[,Sec.fI:=findInterval(PartLoc,c(-1,d1$CumLen),left.open=TRUE)]
d2
# Part PartLoc Sec.fI
# 1: A 0.0 1
# 2: A 7.5 1
# 3: A 10.0 1
# 4: A 20.0 2
# 5: A 35.0 2
# 6: A 45.0 3
# 7: A 49.0 3
另一种方法是使用 data.table
加入。
首先我把每个Section的起始位置添加进去。
d1[,CumLen0:=c(-1,head(CumLen,-1))]
d1
# Part Section SecLen CumLen CumLen0
# 1: A 1 10 10 -1
# 2: A 2 30 40 10
# 3: A 3 9 49 40
然后查找Section。
d2[,Sec.cs:=d1[d2,Section,on=.(CumLen0<PartLoc,CumLen>=PartLoc)]]
d2
# Part PartLoc Sec.fI Sec.cs
# 1: A 0.0 1 1
# 2: A 7.5 1 1
# 3: A 10.0 1 1
# 4: A 20.0 2 2
# 5: A 35.0 2 2
# 6: A 45.0 3 3
# 7: A 49.0 3 3
两种方式都可以。
现在我尝试用更多的Part。
D1 <- data.table(
Part = c("A","A","A","B","B","C"),
Section = c(1,2,3,1,2,1),
SecLen = c(10,30,9,5,20,18) # incorrectly had 10 for the last value
)
D2 <- data.table(
Part = c(rep("A",7),rep("B",3),rep("C",3)),
PartLoc = c(0.0,7.5,10,20,35,45,49,1,12,25,0,9,18)
)
D1[,CumLen:=cumsum(SecLen),by=Part]
D1
# Part Section SecLen CumLen
# 1: A 1 10 10
# 2: A 2 30 40
# 3: A 3 9 49
# 4: B 1 5 5
# 5: B 2 20 25
# 6: C 1 18 18
D2
# Part PartLoc
# 1: A 0.0
# 2: A 7.5
# 3: A 10.0
# 4: A 20.0
# 5: A 35.0
# 6: A 45.0
# 7: A 49.0
# 8: B 1.0
# 9: B 12.0
# 10: B 25.0
# 11: C 0.0
# 12: C 9.0
# 13: C 18.0
我尝试 findInterval
.
D2[,Sec.fI:=findInterval(PartLoc,c(-1,D1$CumLen),left.open=TRUE),by=Part]
# Error in findInterval(PartLoc, c(-1, D1$CumLen), left.open = TRUE) :
# 'vec' must be sorted non-decreasingly and not contain NAs
很明显,它不工作,因为我没有将 D1$CumLen
由Part,所以它是非递减的。
我尝试连接。
D1[,CumLen0:=c(-1,head(CumLen,-1)),by=Part]
D2[,Sec.cs:=D1[D2,Section,on=.(CumLen0<PartLoc,CumLen>=PartLoc),by=Part]]
# Error in vecseq(f__, len__, if (allow.cartesian || notjoin || !anyDuplicated(f__, :
# Join results in 31 rows; more than 19 = nrow(x)+nrow(i).
# Check for duplicate key values in i each of which join to the same group in x over and over again.
# If that's ok, try by=.EACHI to run j for each group to avoid the large allocation.
# If you are sure you wish to proceed, rerun with allow.cartesian=TRUE.
# Otherwise, please search for this error message in the FAQ, Wiki, Stack Overflow and data.table issue tracker for advice.
在这里,我遇到了我对连接的初学知识的限制。我尝试 allow.cartesian=TRUE
按照建议,但我只是确认我莫名其妙地得到了31行,但没有我想要的东西。
D1[D2,Section,on=.(CumLen0<PartLoc,CumLen>=PartLoc),by=Part,allow.cartesian=TRUE]
# Part Section
# 1: A 1
# 2: A 1
# 3: A 1
# 4: A 2
# 5: A 2
# 6: A 3
# 7: A 3
# 8: A 1
# 9: A 2
# 10: A 2
# 11: A 1
# 12: A 1
# 13: A 2
# 14: B 1
# 15: B 2
# 16: B 2
# 17: B 2
# 18: B 1
# 19: B 2
# 20: B 2
# 21: B 1
# 22: B 2
# 23: B 2
# 24: C 1
# 25: C 1
# 26: C 1
# 27: C 1
# 28: C 1
# 29: C 1
# 30: C 1
# 31: C 1
# Part Section
我希望能得到帮助,让这个工作在 data.table
.
编辑我很满意 findInterval
由@Ian Campbell提出的解决方案。我还是有兴趣看看如何让加入工作。
你可以将 D1
随着 .BY
特殊符号。
library(data.table)
D2[,Sec.fI:=findInterval(PartLoc,c(-1,D1[Part == .BY,CumLen]),left.open=TRUE),by=Part][]
Part PartLoc Sec.fI
1: A 0.0 1
2: A 7.5 1
3: A 10.0 1
4: A 20.0 2
5: A 35.0 2
6: A 45.0 3
7: A 49.0 3
8: B 1.0 1
9: B 12.0 2
10: B 25.0 2
11: C 0.0 1
12: C 9.0 1
13: C 18.0 2
见 help("special-symbols")
以获取更多信息。
在你的OP中有点迷茫。至少基于前3句话,这里有一个使用滚动连接的选项。
d1[, LastPage := cumsum(SecLen)]
d2[, Section :=
d1[.SD, on=.(Part, LastPage=PartLoc), roll=-Inf, Section]
]
输出
Part PartLoc Section
1: A 0.0 1
2: A 7.5 1
3: A 10.0 1
4: A 20.0 2
5: A 35.0 2
6: A 45.0 3
7: A 49.0 3
由OP编辑。
我可以确认这对我的情况是有效的,有更多的零件。
D2[, Sec.rJ :=
D1[.SD, on=.(Part, CumLen=PartLoc), roll=-Inf, Section]
][]
# Part PartLoc Sec.rJ
# 1: A 0.0 1
# 2: A 7.5 1
# 3: A 10.0 1
# 4: A 20.0 2
# 5: A 35.0 2
# 6: A 45.0 3
# 7: A 49.0 3
# 8: B 1.0 1
# 9: B 12.0 2
# 10: B 25.0 2
# 11: C 0.0 1
# 12: C 9.0 1
# 13: C 18.0 1