我有两个整数/ posixct向量:
a <- c(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15) #has > 2 mil elements
b <- c(4,6,10,16) # 200000 elements
现在我的结果向量c应该为向量的每个元素包含最近的b:
元素c <- c(4,4,4,4,4,6,6,...)
我尝试使用apply和which.min(abs(a-b)),但它非常慢。
有没有更聪明的方法来解决这个问题?是否有data.table解决方案?
答案 0 :(得分:4)
library(data.table)
a=data.table(Value=c(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15))
a[,merge:=Value]
b=data.table(Value=c(4,6,10,16))
b[,merge:=Value]
setkeyv(a,c('merge'))
setkeyv(b,c('merge'))
Merge_a_b=a[b,roll='nearest']
答案 1 :(得分:2)
不太确定它与您的音量有什么关系,但Intent cameraIntent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
非常快。
我们的想法是在cut
的元素之间的中点处剪切矢量a
。
请注意,我假设b
中的元素严格增加!
这样的事情:
b
使用像a <- c(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15) #has > 2 mil elements
b <- c(4,6,10,16) # 200000 elements
cuts <- c(-Inf, b[-1]-diff(b)/2, Inf)
# Will yield: c(-Inf, 5, 8, 13, Inf)
cut(a, breaks=cuts, labels=b)
# [1] 4 4 4 4 4 6 6 6 10 10 10 10 10 16 16
# Levels: 4 6 10 16
这样的低级函数更快(这也是假设断点不递减)。
findInterval
当然,你可以这样做:
findInterval(a, cuts)
[1] 1 1 1 1 2 2 2 3 3 3 3 3 4 4 4
请注意,您可以通过将相关参数传递给index = findInterval(a, cuts)
b[index]
# [1] 4 4 4 4 6 6 6 10 10 10 10 10 16 16 16
(或a
)来选择与b
元素等距的cut
元素会发生什么情况,请参阅他们的帮助页面。
答案 2 :(得分:1)
如this link中所示,您可以执行以下操作:
which(abs(x-your.number)==min(abs(x-your.number)))
或
which.min(abs(x-your.number))
其中x
是您的向量,your.number
是值
答案 3 :(得分:1)
迟到了聚会,但是DescTools
包中有一个名为Closest
的函数,它几乎可以完全满足您的需要(它不会一次执行多个操作)
要解决此问题,我们可以在您的lapply
列表上a
,找到最接近的列表。
library(DescTools)
lapply(a, function(i) Closest(x = b, a = i))
您可能会注意到,返回的值多于a
中的值。这是因为Closest
将返回两个值,如果您要测试的值恰好在两个之间(例如3恰好在1和5之间,那么将同时返回1和5)。
要解决此问题,请将min
或max
放在结果周围:
lapply(a, function(i) min(Closest(x = b, a = i)))
lapply(a, function(i) max(Closest(x = b, a = i)))
然后unlist
的结果得到纯矢量:)
答案 4 :(得分:1)
对于那些对慢速解决方案感到满意的人:
sapply(a, function(a, b) {b[which.min(abs(a-b))]}, b)
答案 5 :(得分:0)
使用max.col
+ outer
,这可能是一个简单的基本R选项:
b[max.col(-abs(outer(a,b,"-")))]
给出
> b[max.col(-abs(outer(a,b,"-")))]
[1] 4 4 4 4 6 6 6 10 10 10 10 10 16 16 16