Q1: если у вас нет исходных данных, вы не можете использовать hist
.
Q2: с какой-то работой.
Во-первых, barplot
не предоставляет дискретную ось X. Глядя на ваш график, это ясно показано, где интервал между первыми двумя столбцами (2-0,5 = 1,5) такой же, как последние два столбца (42,5-32,5 = 10). Вы можете получить средние точки оси X, посмотрев (невидимое) возвращаемое значение barplot
:
(barplot(df$share, names.arg=df$dist.km,
col="orange", xlab="km", ylab="trips"))
# [,1]
# [1,] 0.7
# [2,] 1.9
# [3,] 3.1
# [4,] 4.3
# [5,] 5.5
# [6,] 6.7
# [7,] 7.9
# [8,] 9.1
# [9,] 10.3
# [10,] 11.5
Точки равноудалены, несмотря на то, что действительные точки не делают этого. Это равное расстояние объясняется тем, что R фактически принимает категориальные данные, а не непрерывные.
Чтобы компенсировать это, мы можем либо отрегулировать ширину графиков, либо расстояние между ними. Если бы мы изменили ширину, то мы бы сравнили ширину с визуальной важностью, чего нам следует избегать, поэтому давайте перейдем к «пробелу»:
(bp <- barplot(df$share, names.arg=df$dist.km,
space = c(0, diff(df$dist.km)),
col="orange", xlab="km", ylab="trips"))
# [,1]
# [1,] 0.5
# [2,] 3.0
# [3,] 6.0
# [4,] 11.5
# [5,] 16.5
# [6,] 22.5
# [7,] 28.5
# [8,] 34.5
# [9,] 40.5
# [10,] 51.5
Чтобы построить нормальную кривую, нам нужно среднее значение исходного распределения и стандартное отклонение. Без исходных данных мы можем аппроксимировать их средневзвешенным значением и средневзвешенным стандартным отклонением, оба из которых предоставлены пакетом Hmisc
.
mu <- Hmisc::wtd.mean(df$dist.km, df$trips)
sigma <- sqrt(Hmisc::wtd.var(df$dist.km, weights = df$trips))
c(mu, sigma)
# [1] 13.565338 8.911899
К сожалению, как мы видим из выходных данных второго barplot
выше, ось X не в том же масштабе, что и данные. К счастью, он все еще непрерывен и линейен для нас, поэтому нам просто нужно приспособиться к этому. Мы можем вычислить его вручную, но для удобства рассмотрим функцию обратного преобразования:
func <- function(a) {
(min(df$dist.km) - bp[1,1]) + # the offset, happens to be 0 here since
# the first datapoint is exactly 0.5
a * diff(range(bp[,1])) / diff(range(df$dist.km))
}
mu2 <- func(mu)
sigma2 <- sigma
c(mu2, sigma2)
# [1] 16.472196 8.911899
Обратите внимание, что мы не корректируем отклонение: напомним (из вашего класса статистики), что когда вы добавляете значение ко всем данным в источнике, статистика "местоположения" (например, среднее значение, медиана) корректируется аналогично (добавьте значение), но разница не изменилась.
Так что теперь мы можем использовать curve
, чтобы добавить это к сюжету:
curve(dnorm(x, mean=mu2, sd=sigma2),
col = "red", lwd = 2, add=TRUE)
Примечание: вызов функции, который мы дали в качестве первого аргумента curve
, нуждается в переменной x
, хотя мы ее не определили. Это используется внутри curve
и заменяется фактическим вектором значений. Может быть другим, возможно с curve(dnorm(yy,...), xname="yy")
.
Эстетически это недостаточно высоко ... мы можем масштабировать его с максимальной частотой:
# start over
bp <- barplot(df$share, names.arg=df$dist.km,
space = c(0, diff(df$dist.km)),
col="orange", xlab="km", ylab="trips")
curve(dnorm(x, mean=mu2, sd=sigma2) / max(df$share),
col = "red", lwd = 2, add=TRUE)
Последняя точка: эта нормальная кривая является приближенной, и, хотя она хорошая, она все еще несовершенна. Если у вас есть исходные данные, было бы гораздо лучше использовать hist
и фактические значения mu / sigma.