1

给出一些像这样绘制的数据点(如下),我将如何获取在特定 y 处相交的相交值。例如,如果我要绘制水平线 y=1000,它会与绘图上的哪些 x 值相交(作为数组)?

我的数据看起来像这样

x <- c(1, 2, 3, 4, ..., )
y <- c(1000, 1200, 900, 700, ..., )

图1 谢谢你。

4

4 回答 4

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]
于 2012-12-07T07:04:10.120 回答
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 个点。

于 2012-12-07T07:33:00.680 回答
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
于 2012-12-07T07:36:58.663 回答
0

我会把你的数据放在一个单一的data.frame

dat = data.frame(x, y)

然后,您可以对数据集进行子集化以仅保留以下值y == 1000

dat[dat$y == 1000,]

请注意,这仅在y您使用的值实际上在数据集中时才有效。如果您 y在数据集中选择一个值(例如y = 996.345),您将不得不对时间序列进行一些插值,请参见例如this SO post,或通过拟合一些样条函数(这可能在范围上效果最好x = [150,900])。

于 2012-12-07T07:04:03.887 回答