Хорошо, несколько вещей, прежде чем мы начнем. Вы используете градусы в вашем seq
, что даст вам неверные результаты (от 0 до 360 градусов). Вы можете проверить, что это неправильно, взяв cos(360)
в R, который не равен 1. Это объясняется в документации для функций триггера в Подробно .
Итак, давайте изменим вашу функцию на эту
xymat <- map_df(data.frame(degrees=seq(0,2*pi,length=360)),
function(theta) data.frame(x = sin(theta), y = cos(theta)))
Если вы наметите это, это действительно будет выглядеть как круг.
Давайте на самом деле ограничим это нижней половиной круга. Если вы проведете сплайн через это, не понимая симметрию и не глядя на график, есть вероятность, что вы получите горизонтальную линию через круг.
Почему? потому что сплайн не знает, что он симметричен выше и ниже y = 0. Сплайн пытается подогнать функцию, которая объясняет «данные», а не прослеживать дугу. Разбивает разницу между двумя симметричными наборами точек вокруг y = 0.
Если мы ограничим сплайн нижней половиной круга, мы можем использовать значения y от 1 до -1, например:
lower.semicircle <- data.frame(predict(smooth.spline(xymat[91:270,], all.knots = T)))
И давайте проведем через него сплайн.
lower.semicircle.pred<-data.frame(predict(smooth.spline(lower.semicircle, all.knots = T)))
Обратите внимание , что я не использую здесь функцию deriv
. Это связано с другой проблемой в примере cars
, с которым вы связаны. Вам нужна полная абсолютная кривизна, и они смотрят на скорость изменения кривизны.
Теперь у нас есть приближение к нижнему полукругу с использованием сплайнов. Теперь вам нужно расстояние между всеми маленькими последовательными точками, как в интеграле со страницы википедии.
Давайте вычислим все расстояния малых дуг, используя матрицу расстояний. Это буквально вычисляет евклидовы расстояния между каждой точкой до каждой другой точки.
all.pairwise.distances.in.the.spline.approx<-dist(lower.semicircle.pred, diag=F)
dist.matrix<-as.matrix(all.pairwise.distances.in.the.spline.approx)
seq.of.distances.you.want<-dist.matrix[row(dist.matrix) == col(dist.matrix) + 1]
Этот последний объект - это то, что вам нужно суммировать.
sum(seq.of.distances.you.want)
.. что соответствует [1] 3.079
для нижнего полукруга, примерно половина вашего ожидаемого значения 2 * пи.
Это не идеально, но у сплайнов есть проблемы с краевыми эффектами.