PowerPivot: Function for distance between two points Error - excel

I am currently using powerpivot and I added a column to create a calculated field for all rows. The purpose of the function is to find the distance between two zip codes by takin their Latitude and Longitude; this function always works in excel worksheets but when I attempt to use the same function in power query, it does not work. The reason why I'm using power query for this function is because the data set is over 4,000,000 rows...
I'm using the function below and it returns as "#ERROR"
=ACOS(COS(RADIANS(90-'Origin vs Destination w PKG'[Latitude]))*COS(RADIANS(90-'Origin vs Destination w PKG'[DLatitude]))+SIN(RADIANS(90-'Origin vs Destination w PKG'[Latitude]))*SIN(RADIANS(90-'Origin vs Destination w PKG'[DLatitude]))*COS(RADIANS('Origin vs Destination w PKG'[Longitude]-'Origin vs Destination w PKG'[DLongitude])))*3958.8
Above is the function. Does anyone know how to get the distance function between two coordinates to work in PowerPivot?
Thanks a lot

Assuming Table1 has 4 columns [Latitude_1], [Longitude_1], [Latitude_2], [Longitude_2] and the coordinates are in decimal [38.892456, -74.0247852] then code below generates the distance between the locations in miles (change 3959 to 6371 for kilometers) using the formula:
=ACOS(SIN(lat1)*SIN(lat2)+COS(lat1)*COS(lat2)*COS(lon2-lon1))*3959
which in powerquery code is:
= Number.Acos(Number.Sin(([Latitude_1] / 180) * Number.PI) * Number.Sin(([Latitude_2] / 180) * Number.PI) + Number.Cos(([Latitude_1] / 180) * Number.PI) * Number.Cos(([Latitude_2] / 180) * Number.PI) * Number.Cos( ([Longitude_2] / 180) * Number.PI-([Longitude_1] / 180) * Number.PI)) * 3959)
full code sample:
let Source = Excel.CurrentWorkbook(){[Name="Table1"]}[Content],
#"Added Custom" = Table.AddColumn(Source, "DistanceMiles", each Number.Acos(Number.Sin(([Latitude_1] / 180) * Number.PI) * Number.Sin(([Latitude_2] / 180) * Number.PI) + Number.Cos(([Latitude_1] / 180) * Number.PI) * Number.Cos(([Latitude_2] / 180) * Number.PI) * Number.Cos( ([Longitude_2] / 180) * Number.PI-([Longitude_1] / 180) * Number.PI)) * 3959),
in #"Added Custom"

Related

Rearrange equation to solve for a different variable

I am looking at VBA code (function) written by someone else.
Here is the code:
Function EuropeanDelta(StrikePrice, MarketPrice, Volatility, InterestRate As Double, PC As String, ValueDate, ExpiryDate As Date, Optional PriceOrYield As String = "P") As Double
Rem Declare our working variables
Dim r As Double
Dim d1 As Double
Dim d2 As Double
Dim t As Double
Dim SqT As Double
Rem End of variable declaration
If PriceOrYield = "Y" Then
MarketPrice = 100 - MarketPrice
StrikePrice = 100 - StrikePrice
If PC = "C" Then
PC = "P"
Else
PC = "C"
End If
End If
Rem Initiase our working variables
t = (ExpiryDate - ValueDate) / 365
SqT = Sqr(t)
r = Application.WorksheetFunction.Ln(1 + InterestRate)
d1 = (Application.WorksheetFunction.Ln(MarketPrice / StrikePrice) + (Volatility * Volatility * 0.5) * t) / (Volatility * SqT)
Rem Quick logic to deal with Calls or Puts
If PC = "C" Then
EuropeanDelta = Exp(-r * t) * Application.WorksheetFunction.NormSDist(d1)
Else
EuropeanDelta = -Exp(-r * t) * Application.WorksheetFunction.NormSDist(-d1)
End If
If PriceOrYield = "Y" Then
EuropeanDelta = EuropeanDelta * -1
End If
End Function
The whole problem is based around the line for "d1". I would like to re-organise to solve for "StrikePrice". I have tried writing it out mathematically and then re-arranging, then swapping back to VBA.
#duffymo is correct, but am giving the answer directly in terms of VBA code
' d1 = (Log(MarketPrice / StrikePrice) + (Volatility * Volatility * 0.5) * t) / (Volatility * Sqr(t))
'
' Volatility * Sqr(t) * d1 = Log(MarketPrice / StrikePrice) + Volatility^2 * t/2
'
' Log(MarketPrice / StrikePrice) = Volatility * Sqr(t) * d1 - Volatility^2 * t/2
'
' MarketPrice / StrikePrice = Exp(Volatility * Sqr(t) * d1 - Volatility^2 * t/2)
'
StrikePrice = MarketPrice / Exp(Volatility * Sqr(t) * d1 - Volatility^2 * t/2)
Other Notes :
For brevity replace Application.WorksheetFunction.Ln() with Log()
There is no need cache SqT = Sqr(t) since it is only used once.
For clarity replace Volatility*Volatility with Volatility^2 as internally it does the same thing.
This is just algebra - high school math.
Take it in steps. Make sure you do the same operation to both sides to make sure that equality still holds.
Here's your starting equation:
d = {ln(m/s) + v*v*t/2}/(v*sqrt(t))
Multiply both sides by the denominator of the RHS:
d*v*sqrt(t) = ln(m/s) + v*v*t/2
Subtract v*v*t/2 from both sides:
(d*v*sqrt(t) - v*v*t/2) = ln(m/s)
Apply the exponential function to both sides, noting that exp(ln(x)) = x:
exp(d*v*sqrt(t) - v*v*t/2) = m/s
Multiply both sides by s:
s*exp(d*v*sqrt(t) - v*v*t/2) = m
Divide both sides by exp(d*v*sqrt(t) - v*v*t/2) to get the desired result:
s = m/exp(d*v*sqrt(t) - v*v*t/2)
Let's see if this function makes sense.
At t = 0 the denominator exp(0) = 1, so the strike price is equal to the market price.
As t -> infinity, we hope that the denominator gets large so s -> zero. L'Hospital's Rule will help here.

Why i cant use acos function

I have a problem with this function. Excel return #name error.
=ACOS(COS(RADIANS(90-B3)) * COS(RADIANS(90-$G$3)) + SIN(RADIANS(90-B3)) * SIN(RADIANS(90-$G$3)) * COS(RADIANS(C3-$G$4))) * 6371

Call Local Function in Postgres Query

I have a function which queries my database to find nearby users. However, my database stores the longitude and latitude of users, and to find the distance from the user, I need to call a function (distance) to check which users to return in the query. Is there a way to do what I have in the code (call my local distance function inside my querystring?)
exports.getNearby = function (longitude, latitude) {
var long1 = longitude;
var lat1 = latitude;
return new Promise(((resolve, reject) => {
const queryString = `SELECT ${userModel.userId}
FROM ${userModel.collectionName} where SELECT distance(${userLocationModel.latitude},
${userLocationModel.longitude}, ${lat1}, ${long1}) < 4`;
db.query(queryString, (err, res) => {
if (err) {
logger.log('error', ` getUser - ${userIdArr} - ${err}`);
reject(err);
} else {
resolve(res.rows[0]);
}
});
}));
};
function distance(lat1, lon1, lat2, lon2) { //returns in km
return 12742 * asin(sqrt(0.5 - cos((lat2 - lat1) * 0.01745329252)/2
+ cos(lat1 * 0.01745329252) * cos(lat2 * 0.01745329252) *
(1 - cos((lon2 - lon1) * 0.01745329252)) / 2));
}
Function written in Postgres (as suggested by #LaurenzAlbe)
CREATE FUNCTION distance(
lat1 double precision,
lng1 double precision,
lat2 double precision,
lng2 double precision
) RETURNS double precision AS
'SELECT 12742
* asin(
|/ (
0.5 - cos(
(lat2 - lat1) * 0.01745329252
)/2
+ cos(lat1 * 0.01745329252)
* cos(lat2 * 0.01745329252)
* (1 - cos(
(lon2 - lon1) * 0.01745329252
)) / 2
)
)'
LANGUAGE sql IMMUTABLE;
If you want to use the function in an SQL statement, you have to define it inside the database using CREATE FUNCTION.
For a function like that, I'd choose LANGUAGE sql.
Have you considered using the PostGIS extension if you want to do geographical data processing inside the database? It offers all imaginable functions out of the box.
Here is how your function could look as SQL function:
CREATE FUNCTION distance(
lat1 double precision,
lng1 double precision,
lat2 double precision,
lng2 double precision
) RETURNS double precision AS
'SELECT 12742
* asin(
|/ (
0.5 - cos(
(lat2 - lat1) * 0.01745329252
)/2
+ cos(lat1 * 0.01745329252)
* cos(lat2 * 0.01745329252)
* (1 - cos(
(lon2 - lon1) * 0.01745329252
)) / 2
)
)'
LANGUAGE sql IMMUTABLE;

how to Calculate google map circle radius js to C#

I know how to use the javascript to calculate the radius by using the below code
var center = new google.maps.LatLng(3.2987599, 102.6872022);
var latLng = new google.maps.LatLng(3.0987599, 101.6872022);
var distanceInMetres = google.maps.geometry.spherical.computeDistanceBetween(center, latLng);
But how to convert the google.maps.geometry.spherical.computeDistanceBetween into C# function?
Distance between 2 points: (lat1,lon1) to (lat2,lon2)
distance = acos(
cos(lat1 * (PI()/180)) *
cos(lon1 * (PI()/180)) *
cos(lat2 * (PI()/180)) *
cos(lon2 * (PI()/180))
+
cos(lat1 * (PI()/180)) *
sin(lon1 * (PI()/180)) *
cos(lat2 * (PI()/180)) *
sin(lon2 * (PI()/180))
+
sin(lat1 * (PI()/180)) *
sin(lat2 * (PI()/180))
) * 3959
3959 is the Earth radius in Miles. Replace this value with
radius in KM, (or any other unit), to get results on the same unit.
You can verify your implementation by comparing to this worked example:
i have write the C# solution to calculate the distance to convert
var distanceInMetres = google.maps.geometry.spherical.computeDistanceBetween(center, latLng);
into C#. Below is the code i have using. 6371 is the radius of the Earth.
//Calculate distance earth between 2 coordinate point
double e = lat * (Math.PI / 180);
double f = lng * (Math.PI / 180);
double g = lat2 * (Math.PI / 180);
double h = lng2 * (Math.PI / 180);
double i =
(Math.Cos(e) * Math.Cos(g) * Math.Cos(f) * Math.Cos(h)
+ Math.Cos(e) * Math.Sin(f) * Math.Cos(g) * Math.Sin(h)
+ Math.Sin(e) * Math.Sin(g));
double j = Math.Acos(i);
double k = (6371 * j); //Distance in KM
The distance between 2 lat/long points can be calculated with the haversine formula, which is described here http://en.wikipedia.org/wiki/Haversine_formula
There also is another question here at stackoverflow about more or less the same issue: Calculate distance between two latitude-longitude points? (Haversine formula)

How can I get Normal Vector of Sphere?

I have to implement simple ray tracing algorithm, but I can not figure out How can I get Normal Vector of the sphere If I have the origin and radius of the sphere and the direction of the ray.
thanks
Wiki aboute sphere but i can not figure it out of this
I have find the solution: here is the code in C#:
Double alpha = Math.Asin(sphere.Radius / (Math.Sqrt(Math.Pow(sphere.Origin.X-ray.Origin.X,2)+Math.Pow(sphere.Origin.Y-ray.Origin.Y,2)+Math.Pow(sphere.Origin.Z-ray.Origin.Z,2))));
Double beta = Math.Acos((ray.Direction * (sphere.Origin - ray.Origin)) / (ray.Direction.Length * (sphere.Origin - ray.Origin).Length));
ray.HitParam = VypA(sphere.Origin - ray.Origin, beta, sphere.Radius) / ray.Direction.Length;
Vector4 g = ray.Origin + ray.Direction * ray.HitParam;
ray.HitNormal = (g - sphere.Origin).Normalized;
////the VypA function
public static Double VypA(Vector4 b, Double beta, Double radius)
{
return b.Length * (Math.Cos(beta) - Math.Sqrt(((radius * radius) / (b.Length2) - (Math.Sin(beta) * (Math.Sin(beta))))));
}

Resources