给出一些像这样(下图)绘制的数据点,我将如何获得在特定y处相交的交叉值。例如,如果我要绘制水平线y = 1000,那么它将与图形中的x值相交(作为数组)?
我的数据看起来像这样
x <- c(1, 2, 3, 4, ..., )
y <- c(1000, 1200, 900, 700, ..., )
谢谢。
答案 0 :(得分:5)
要查看函数y = f(x)(我假设是连续的)与水平线y = h相交的位置,您可以查找f(x)-h中的符号变化。此符号更改的位置是函数穿过该行的位置。除非您了解有关函数的更多详细信息,以便可以在数据点之间进行插值,否则这可能是您所希望的最佳效果。
要计算R中的符号更改,您可以使用以下代码:
h <- 1000
d <- y - h
signChanges <- (d[1:(length(d)-1)] * d[2:length(d)]) <= 0
生成的数组将比x
数组少一个元素,因为每个元素对应于两个相邻x
值之间的间隔。如果该行上的数据点完全,则该数组将包含两个后续TRUE
值。如果这是一个问题,那么你可以插入
d <- ifelse(d == 0, 1, d)
将数据点稍微移动。
要获得相应的x
值,您可以使用每个区间的中心:
x2 <- (x[c(signChanges, FALSE)] + x[c(FALSE, signChanges)])/2
或者您可以在两个相邻数据点之间执行线性插值:
left <- c(signChanges, FALSE)
right <- c(FALSE, signChanges)
t <- (h - y[left])/(y[right] - y[left])
x2 <- (1 - t)*x[left] + t*x[right]
答案 1 :(得分:5)
在没有平滑的情况下查找阈值交叉很少给出明确定义的值。玩下面的内容:
data(sunspots)
sunspots = as.numeric(sunspots)
smoothover = 21 # Try smaller values here to see the failure
y = filter(sunspots,rep(1/smoothover,smoothover),circular=TRUE)
plot(y)
thresh =30
abline(h=thresh)
cross = which(diff(sign(y-thresh))!=0)-1
rug(cross)
如果你想得到“精确”的阈值交叉(如果平滑是如此重要,那么究竟是什么?)你应该首先使用上面的近似来获得交叉点周围的区域,然后进行二次或线性插值,例如: 5分。
答案 2 :(得分:3)
要获得实际的交叉点,您可以使用几个R的空间包:
library(sp)
library(rgeos) ## for gIntersection()
## Wrap your line up as a SpatialLines object
x <- c(1, 2, 3, 4)
y <- c(1000, 1200, 900, 700)
SL1 <- SpatialLines(list(Lines(Line(cbind(x,y)), "A")))
## Create a horizontal SpatialLines object
SL2 <- SpatialLines(list(Lines(Line(cbind(range(x), 1010)), "B")))
## Find their point(s) of intersection
coordinates(gIntersection(SL1, SL2))
# x y
# 1 1.050000 1010
# 1 2.633333 1010
答案 3 :(得分:0)
我会将您的数据放在一个data.frame
中:
dat = data.frame(x, y)
然后,您可以对数据集进行子集化,以仅保留y == 1000
:
dat[dat$y == 1000,]
请注意,这仅适用于您使用的y
值实际位于数据集中的情况。如果您在de数据集中选择y
值不是字面意义(例如y = 996.345
),则必须对时间序列进行一些插值,例如, this SO post,或者通过拟合一些样条函数(这可能最适合范围x = [150,900]
)。