Skip to main content
cancel
Showing results for 
Search instead for 
Did you mean: 

Find everything you need to get certified on Fabric—skills challenges, live sessions, exam prep, role guidance, and more. Get started

Reply
Joaomatos2002
Frequent Visitor

Calculating Sequential Distance in Power BI

Hi,

 

I hope this message finds you well.

 

I am currently facing difficulties creating a DAX measure or power query code to calculate the local distance between the most recent activity and the previous one, with all the data already present in a single table. Despite extensive research, all the examples I’ve found involve two tables, which doesn't apply to my situation.

 

The table contains the following columns: the ID of the card that performed the activity, the activity ID, the location ID, the registration date (note that an activity may start on the 10th, for example, but the relevant date is the end date, so in this case, the date would actually be the 11th), start and end date/time, latitude, and longitude.

 

The goal is for the user to be able to filter the data by the card ID and then by the registration date. Once filtered, the data should be organised by date and time, and the measure I intend to create should calculate the distance from the location of the previous record.

 

I realise this might sound a bit confusing, so let me clarify with some example data:

 

ID_CARDID_ACTIVITYID_LOCATIONCALDAYSTARTTIMEENDTIMElatitudelongitude
AXXXX-XXXX-XXXX-XXXXX16X111/08/202411/08/2024 03:5111/08/2024 04:0241.00000-8.00000
AXXXX-XXXX-XXXX-XXXXX1X211/08/202411/08/2024 04:0711/08/2024 04:1741.00001-8.00001
AXXXX-XXXX-XXXX-XXXXX2X311/08/202411/08/2024 04:2911/08/2024 04:5941.00002-8.00002
AXXXX-XXXX-XXXX-XXXXX3X411/08/202411/08/2024 06:1911/08/2024 06:4441.00003-8.00003
AXXXX-XXXX-XXXX-XXXXX4X411/08/202411/08/2024 07:3711/08/2024 08:1041.00004-8.00004
BXXXX-XXXX-XXXX-XXXXX5X611/08/202411/08/2024 07:5411/08/2024 08:5841.00005-8.00005
AXXXX-XXXX-XXXX-XXXXX6X611/08/202411/08/2024 08:3711/08/2024 08:4041.00006-8.00006
AXXXX-XXXX-XXXX-XXXXX7X711/08/202411/08/2024 08:4011/08/2024 09:4541.00007-8.00007
BXXXX-XXXX-XXXX-XXXXX8X511/08/202411/08/2024 18:0611/08/2024 18:3241.00008-8.00008
BXXXX-XXXX-XXXX-XXXXX9XX711/08/202411/08/2024 18:3311/08/2024 18:5641.00009-8.00009
BXXXX-XXXX-XXXX-XXXXX10X711/08/202411/08/2024 18:5711/08/2024 19:3441.00010-8.00010
BXXXX-XXXX-XXXX-XXXXX11X911/08/202411/08/2024 19:3511/08/2024 19:5941.00011-8.00011
BXXXX-XXXX-XXXX-XXXXX12X211/08/202411/08/2024 20:0111/08/2024 20:2141.00012-8.00012
BXXXX-XXXX-XXXX-XXXXX13X311/08/202411/08/2024 20:2311/08/2024 21:3741.00013-8.00013
AXXXX-XXXX-XXXX-XXXXX14X811/08/202411/08/2024 20:5711/08/2024 22:0041.00014-8.00014
AXXXX-XXXX-XXXX-XXXXX15X911/08/202411/08/2024 22:0311/08/2024 22:3441.00015-8.00015


Let's suppose that these are the data stored in the database.
Now I will show what the user will see when filtering on the dashboard.

 

ID_CARDID_ACTIVITYID_LOCATIONCALDAYSTARTTIMEENDTIMElatitudelongitude

.distanceKM

AXXXX-XXXX-XXXX-XXXXX16X111/08/202411/08/2024 03:5111/08/2024 04:0241.00000-8.000000.0
AXXXX-XXXX-XXXX-XXXXX1X211/08/202411/08/2024 04:0711/08/2024 04:1741.00001-8.000010.2
AXXXX-XXXX-XXXX-XXXXX2X311/08/202411/08/2024 04:2911/08/2024 04:5941.00002-8.000020.4
AXXXX-XXXX-XXXX-XXXXX3X411/08/202411/08/2024 06:1911/08/2024 06:4441.00003-8.000030.7
AXXXX-XXXX-XXXX-XXXXX4X411/08/202411/08/2024 07:3711/08/2024 08:1041.00004-8.000040.0
AXXXX-XXXX-XXXX-XXXXX6X611/08/202411/08/2024 08:3711/08/2024 08:4041.00006-8.000061.0
AXXXX-XXXX-XXXX-XXXXX7X711/08/202411/08/2024 08:4011/08/2024 09:4541.00007-8.000070.9
AXXXX-XXXX-XXXX-XXXXX14X811/08/202411/08/2024 20:5711/08/2024 22:0041.00014-8.000140.2
AXXXX-XXXX-XXXX-XXXXX15X911/08/202411/08/2024 22:0311/08/2024 22:3441.00015-8.000150.5

 

This is what the user will see when applying the filters; the .distanceKM will be calculated in the order of the records.
I hope this is enough for you to understand my question. I look forward to the resolution of this issue or even a suggestion.

 

P.S.: I had to create random data to protect confidential information, but I think the idea is clear.

2 ACCEPTED SOLUTIONS
v-cgao-msft
Community Support
Community Support

Hi @Joaomatos2002 ,

Not sure I understand your question. Please check the M code below:

let
    Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("hdRLjsMgEATQq4y8TiZU82c3cwpLke9/jQEmUtmQNF5YuCz1E79+Pref7bbt9blfXztC+4H6Ah4mPcSIu3x8GVs8hsgVIzVy+DbtqcN7eg2Pm4K1XDSrFo5ThEgLtKBajdmtbkmeIp9pCS1RrcbsTrNCwWiF4hwtS8uqlltasdhxDVOBoeVouW79frB8y4Nu+TFKxSdanpZX5xWWVno3L3eaV6AVVKuV2aNu9cLnKBfnaUVaUV3DthZ9IT9ZSMWEKbKn+5VoJdXKPdcm1irbKfKBWCaWVayfqBXmhx1DLpanHuwcMDrWW0fWsFrZT9HpOoOtA9AxWfUpMcVgigTE2DsgOmZXjapVHvZM8H8XXhibB/Tmgd49ko6NeyZSDG8Z2D3gdMyv9qxVHmcmlwPC9lGHx/EH", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [ID_CARD = _t, ID_ACTIVITY = _t, ID_LOCATION = _t, CALDAY = _t, STARTTIME = _t, ENDTIME = _t, latitude = _t, longitude = _t]),
    #"Changed Type" = Table.TransformColumnTypes(Source,{{"STARTTIME", type datetime}, {"ENDTIME", type datetime}, {"latitude", type number}, {"longitude", type number}}),
    #"Sorted Rows" = Table.Sort(#"Changed Type",{{"ID_CARD", Order.Ascending}, {"ENDTIME", Order.Ascending}}),
    #"Added Index" = Table.AddIndexColumn(#"Sorted Rows", "Index", 1, 1, Int64.Type),
    AddPreviousIndex = Table.AddColumn(#"Added Index", "PreviousIndex", each [Index] - 1),
    MergedQueries = Table.NestedJoin(AddPreviousIndex, {"ID_CARD", "PreviousIndex"}, AddPreviousIndex, {"ID_CARD", "Index"}, "PreviousRow", JoinKind.LeftOuter),
    ExpandedTable = Table.ExpandTableColumn(MergedQueries, "PreviousRow", {"latitude", "longitude"}, {"Prev_latitude", "Prev_longitude"}),
    AddDistanceColumn = Table.AddColumn(ExpandedTable, "Distance_km", each 
        let
            lat1 = [latitude] * Number.PI / 180,
            lon1 = [longitude] * Number.PI / 180,
            lat2 = [Prev_latitude] * Number.PI / 180,
            lon2 = [Prev_longitude] * Number.PI / 180,
            dlat = lat2 - lat1,
            dlon = lon2 - lon1,
            a = Number.Sin(dlat / 2) * Number.Sin(dlat / 2) + Number.Cos(lat1) * Number.Cos(lat2) * Number.Sin(dlon / 2) * Number.Sin(dlon / 2),
            c = 2 * Number.Atan2(Number.Sqrt(a), Number.Sqrt(1 - a)),
            R = 6371, // Radius of Earth in kilometers
            distance = R * c
        in
            distance
    ),
    #"Removed Columns" = Table.RemoveColumns(AddDistanceColumn,{"Index", "PreviousIndex", "Prev_latitude", "Prev_longitude"})
in
    #"Removed Columns"

vcgaomsft_0-1723613520136.png

If I have misunderstood your question, please feel free to contact me.

Best Regards,
Gao

Community Support Team

 

If there is any post helps, then please consider Accept it as the solution  to help the other members find it more quickly.
If I misunderstand your needs or you still have problems on it, please feel free to let us know. Thanks a lot!

How to get your questions answered quickly --  How to provide sample data in the Power BI Forum

View solution in original post

dufoq3
Super User
Super User

Hi @Joaomatos2002, I've already replied to you here with both Power Query and DAX solutions.

 


Note: Check this link to learn how to use my query.
Check this link if you don't know how to provide sample data.

View solution in original post

3 REPLIES 3
dufoq3
Super User
Super User

Hi @Joaomatos2002, I've already replied to you here with both Power Query and DAX solutions.

 


Note: Check this link to learn how to use my query.
Check this link if you don't know how to provide sample data.

v-cgao-msft
Community Support
Community Support

Hi @Joaomatos2002 ,

Not sure I understand your question. Please check the M code below:

let
    Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("hdRLjsMgEATQq4y8TiZU82c3cwpLke9/jQEmUtmQNF5YuCz1E79+Pref7bbt9blfXztC+4H6Ah4mPcSIu3x8GVs8hsgVIzVy+DbtqcN7eg2Pm4K1XDSrFo5ThEgLtKBajdmtbkmeIp9pCS1RrcbsTrNCwWiF4hwtS8uqlltasdhxDVOBoeVouW79frB8y4Nu+TFKxSdanpZX5xWWVno3L3eaV6AVVKuV2aNu9cLnKBfnaUVaUV3DthZ9IT9ZSMWEKbKn+5VoJdXKPdcm1irbKfKBWCaWVayfqBXmhx1DLpanHuwcMDrWW0fWsFrZT9HpOoOtA9AxWfUpMcVgigTE2DsgOmZXjapVHvZM8H8XXhibB/Tmgd49ko6NeyZSDG8Z2D3gdMyv9qxVHmcmlwPC9lGHx/EH", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [ID_CARD = _t, ID_ACTIVITY = _t, ID_LOCATION = _t, CALDAY = _t, STARTTIME = _t, ENDTIME = _t, latitude = _t, longitude = _t]),
    #"Changed Type" = Table.TransformColumnTypes(Source,{{"STARTTIME", type datetime}, {"ENDTIME", type datetime}, {"latitude", type number}, {"longitude", type number}}),
    #"Sorted Rows" = Table.Sort(#"Changed Type",{{"ID_CARD", Order.Ascending}, {"ENDTIME", Order.Ascending}}),
    #"Added Index" = Table.AddIndexColumn(#"Sorted Rows", "Index", 1, 1, Int64.Type),
    AddPreviousIndex = Table.AddColumn(#"Added Index", "PreviousIndex", each [Index] - 1),
    MergedQueries = Table.NestedJoin(AddPreviousIndex, {"ID_CARD", "PreviousIndex"}, AddPreviousIndex, {"ID_CARD", "Index"}, "PreviousRow", JoinKind.LeftOuter),
    ExpandedTable = Table.ExpandTableColumn(MergedQueries, "PreviousRow", {"latitude", "longitude"}, {"Prev_latitude", "Prev_longitude"}),
    AddDistanceColumn = Table.AddColumn(ExpandedTable, "Distance_km", each 
        let
            lat1 = [latitude] * Number.PI / 180,
            lon1 = [longitude] * Number.PI / 180,
            lat2 = [Prev_latitude] * Number.PI / 180,
            lon2 = [Prev_longitude] * Number.PI / 180,
            dlat = lat2 - lat1,
            dlon = lon2 - lon1,
            a = Number.Sin(dlat / 2) * Number.Sin(dlat / 2) + Number.Cos(lat1) * Number.Cos(lat2) * Number.Sin(dlon / 2) * Number.Sin(dlon / 2),
            c = 2 * Number.Atan2(Number.Sqrt(a), Number.Sqrt(1 - a)),
            R = 6371, // Radius of Earth in kilometers
            distance = R * c
        in
            distance
    ),
    #"Removed Columns" = Table.RemoveColumns(AddDistanceColumn,{"Index", "PreviousIndex", "Prev_latitude", "Prev_longitude"})
in
    #"Removed Columns"

vcgaomsft_0-1723613520136.png

If I have misunderstood your question, please feel free to contact me.

Best Regards,
Gao

Community Support Team

 

If there is any post helps, then please consider Accept it as the solution  to help the other members find it more quickly.
If I misunderstand your needs or you still have problems on it, please feel free to let us know. Thanks a lot!

How to get your questions answered quickly --  How to provide sample data in the Power BI Forum

lbendlin
Super User
Super User

Please define "local".  What is the maximum distance you expect, and where is the geographical center? Usually distances are calculated via the Great Circle formula or Haversine.

Helpful resources

Announcements
Europe Fabric Conference

Europe’s largest Microsoft Fabric Community Conference

Join the community in Stockholm for expert Microsoft Fabric learning including a very exciting keynote from Arun Ulag, Corporate Vice President, Azure Data.

AugPowerBI_Carousel

Power BI Monthly Update - August 2024

Check out the August 2024 Power BI update to learn about new features.

August Carousel

Fabric Community Update - August 2024

Find out what's new and trending in the Fabric Community.

Top Solution Authors
Top Kudoed Authors