NetworkAnalysis¶
Class for doing network analysis.
- class NetworkAnalysis(network, rules, log=True, detailed_log=False)[source]¶
Bases:
object
Class for doing network analysis.
The class takes a GeoDataFrame of line geometries and rules for the analyses, and holds methods for doing network analysis based on GeoDataFrames of origin and destination points.
The ‘od_cost_matrix’ method is the fastest, and returns a DataFrame with only indices and travel costs between each origin-destination pair.
The ‘get_route’ method does the same, but also returns the line geometry of the routes. ‘get_k_routes’ can be used to find multiple routes between each OD pair.
The service_area methods only take a set of origins, and return the lines that can be reached within one or more breaks.
The ‘get_route_frequencies’ method is a bit different. It returns the individual line segments that were visited with an added column for how many times the segments were used.
- Parameters:
network (GeoDataFrame)
rules (NetworkAnalysisRules | dict)
log (bool)
detailed_log (bool)
- network¶
A Network instance that holds the lines and nodes (points).
- rules¶
NetworkAnalysisRules instance.
- log¶
A DataFrame with information about each analysis run.
Examples:¶
Read example data.
>>> import sgis as sg >>> roads = sg.read_parquet_url("https://media.githubusercontent.com/media/statisticsnorway/ssb-sgis/main/tests/testdata/roads_oslo_2022.parquet")
Preparing the lines for directed network analysis.
>>> connected_roads = sg.get_connected_components(roads).query("connected == 1")
>>> directed_roads = sg.make_directed_network( ... connected_roads, ... direction_col="oneway", ... direction_vals_bft=("B", "FT", "TF"), ... minute_cols=("drivetime_fw", "drivetime_bw"), ... dropnegative=True, ... dropna=True, ... )
>>> rules = sg.NetworkAnalysisRules(weight="minutes", directed=True) >>> nwa = sg.NetworkAnalysis(network=directed_roads, rules=rules, detailed_log=False) >>> nwa NetworkAnalysis( network=Network(6364 km, percent_bidirectional=87), rules=NetworkAnalysisRules(weight=minutes, directed=True, search_tolerance=250, search_factor=0, split_lines=False, ...), log=True, detailed_log=True, )
Now we’re ready for network analysis.
- copy(deep=True)[source]¶
Returns a (deep) copy of the class instance.
- Parameters:
deep (
bool
) – Whether to return a deep or shallow copy. Defaults to True.- Return type:
- get_k_routes(origins, destinations, *, k, drop_middle_percent, rowwise=False, destination_count=None, cutoff=None)[source]¶
Returns the geometry of 1 or more routes between origins and destinations.
Finds the route with the lowest cost (minutes, meters, etc.) from a set of origins to a set of destinations. Then the middle part of the route is removed from the graph the new low-cost path is found. Repeats k times. If k=1, it is identical to the get_route method.
- Parameters:
origins (
GeoDataFrame
) – GeoDataFrame of points from where the routes will originate.destinations (
GeoDataFrame
) – GeoDataFrame of points from where the routes will terminate.k (
int
) – the number of low-cost routes to find.drop_middle_percent (
int
) – how many percent of the middle part of the routes that should be removed from the graph before the next k route is calculated. If set to 100, only the median edge will be removed. If set to 0, all but the first and last edge will be removed. The graph is copied for each od pair.rowwise (
bool
) – if False (default), it will calculate the cost from each origins to each destination. If true, it will calculate the cost from origin 1 to destination 1, origin 2 to destination 2 and so on.destination_count (
int
|None
) – number of closest destinations to keep for each origin. If None (default), all trips will be included. The number of destinations might be higher than the destination_count if trips have equal cost.cutoff (
int
|float
|None
) – the maximum cost (weight) for the trips. Defaults to None, meaning all rows will be included. NaNs will also be removed if cutoff is specified.
- Return type:
GeoDataFrame
- Returns:
A DataFrame with the geometry of the k routes between origin and destination. Also returns the column ‘k’, a weight column and the columns ‘origin’ and ‘destination’, containing the indices of the origins and destinations GeoDataFrames.
Note
How many percent of the route to drop from the graph, will determine how many k routes will be found. If 100 percent of the route is dropped, it is very hard to find more than one path for each OD pair. If ‘drop_middle_percent’ is 1, the resulting routes might be very similar, depending on the layout of the network.
- Raises:
ValueError – if drop_middle_percent is not between 0 and 100.
- Parameters:
origins (GeoDataFrame)
destinations (GeoDataFrame)
k (int)
drop_middle_percent (int)
rowwise (bool)
destination_count (int | None)
cutoff (int | float | None)
- Return type:
GeoDataFrame
Examples:¶
Create the NetworkAnalysis instance.
>>> import sgis as sg >>> roads = sg.read_parquet_url('https://media.githubusercontent.com/media/statisticsnorway/ssb-sgis/main/tests/testdata/roads_oslo_2022.parquet') >>> directed_roads = sg.get_connected_components(roads).loc[lambda x: x["connected"] == 1].pipe(sg.make_directed_network_norway, dropnegative=True) >>> rules = sg.NetworkAnalysisRules(weight="minutes", directed=True) >>> nwa = sg.NetworkAnalysis(network=directed_roads, rules=rules, detailed_log=False)
Getting 10 fastest routes from one point to another point.
>>> points = sg.read_parquet_url('https://media.githubusercontent.com/media/statisticsnorway/ssb-sgis/main/tests/testdata/points_oslo.parquet') >>> point1 = points.iloc[[0]] >>> point2 = points.iloc[[1]]
>>> k_routes = nwa.get_k_routes( ... point1, ... point2, ... k=10, ... drop_middle_percent=1 ... ) >>> k_routes origin destination minutes k geometry 0 0 1 13.039830 1 MULTILINESTRING Z ((272281.367 6653079.745 160... 1 0 1 14.084324 2 MULTILINESTRING Z ((272281.367 6653079.745 160... 2 0 1 14.238108 3 MULTILINESTRING Z ((272281.367 6653079.745 160... 3 0 1 14.897682 4 MULTILINESTRING Z ((271257.900 6654378.100 193... 4 0 1 14.962593 5 MULTILINESTRING Z ((271257.900 6654378.100 193... 5 0 1 15.423934 6 MULTILINESTRING Z ((272281.367 6653079.745 160... 6 0 1 16.217271 7 MULTILINESTRING Z ((272281.367 6653079.745 160... 7 0 1 16.483982 8 MULTILINESTRING Z ((272281.367 6653079.745 160... 8 0 1 16.513253 9 MULTILINESTRING Z ((272281.367 6653079.745 160... 9 0 1 16.551196 10 MULTILINESTRING Z ((272281.367 6653079.745 160...
We got all 10 routes because only the middle 1 percent of the routes are removed in each iteration. Let’s compare with dropping middle 50 and middle 100 percent.
>>> k_routes = nwa.get_k_routes( ... point1, ... point2, ... k=10, ... drop_middle_percent=50 ... ) >>> k_routes origin destination minutes k geometry 0 0 1 13.039830 1 MULTILINESTRING Z ((272281.367 6653079.745 160... 1 0 1 14.238108 2 MULTILINESTRING Z ((272281.367 6653079.745 160... 2 0 1 20.139294 3 MULTILINESTRING Z ((272281.367 6653079.745 160... 3 0 1 23.506778 4 MULTILINESTRING Z ((265226.515 6650674.617 88....
>>> k_routes = nwa.get_k_routes( ... point1, ... point2, ... k=10, ... drop_middle_percent=100 ... ) >>> k_routes origin destination minutes k geometry 0 0 1 13.03983 1 MULTILINESTRING Z ((272281.367 6653079.745 160...
- get_route(origins, destinations, *, rowwise=False, destination_count=None, cutoff=None)[source]¶
Returns the geometry of the low-cost route between origins and destinations.
Finds the route with the lowest cost (minutes, meters, etc.) from a set of origins to a set of destinations. If the weight is meters, the shortest route will be found. If the weight is minutes, the fastest route will be found.
- Parameters:
origins (
GeoDataFrame
) – GeoDataFrame of points from where the routes will originatedestinations (
GeoDataFrame
) – GeoDataFrame of points from where the routes will terminate.rowwise (
bool
) – if False (default), it will calculate the cost from each origins to each destination. If true, it will calculate the cost from origin 1 to destination 1, origin 2 to destination 2 and so on.destination_count (
int
|None
) – number of closest destinations to keep for each origin. If None (default), all trips will be included. The number of destinations might be higher than the destination_count if trips have equal cost.cutoff (
int
|float
|None
) – the maximum cost (weight) for the trips. Defaults to None, meaning all rows will be included. NaNs will also be removed if cutoff is specified.
- Return type:
GeoDataFrame
- Returns:
A DataFrame with the geometry of the routes between origin and destination. Also returns a weight column and the columns ‘origin’ and ‘destination’, containing the indices of the origins and destinations GeoDataFrames.
Examples:¶
Create the NetworkAnalysis instance.
>>> import sgis as sg >>> roads = sg.read_parquet_url("https://media.githubusercontent.com/media/statisticsnorway/ssb-sgis/main/tests/testdata/roads_oslo_2022.parquet") >>> directed_roads = sg.get_connected_components(roads).loc[lambda x: x["connected"] == 1].pipe(sg.make_directed_network_norway, dropnegative=True) >>> rules = sg.NetworkAnalysisRules(weight="minutes", directed=True) >>> nwa = sg.NetworkAnalysis(network=directed_roads, rules=rules, detailed_log=False)
Get routes from 1 to 1000 points.
>>> points = sg.read_parquet_url("https://media.githubusercontent.com/media/statisticsnorway/ssb-sgis/main/tests/testdata/points_oslo.parquet")
>>> routes = nwa.get_route(points.iloc[[0]], points) >>> routes origin destination minutes geometry 0 1 2 12.930588 MULTILINESTRING Z ((272281.367 6653079.745 160... 1 1 3 10.867076 MULTILINESTRING Z ((270054.367 6653367.774 144... 2 1 4 8.075722 MULTILINESTRING Z ((259735.774 6650362.886 24.... 3 1 5 14.659333 MULTILINESTRING Z ((272281.367 6653079.745 160... 4 1 6 14.406460 MULTILINESTRING Z ((257034.948 6652685.595 156... .. ... ... ... ... 992 1 996 10.858519 MULTILINESTRING Z ((266881.100 6647824.860 132... 993 1 997 7.461032 MULTILINESTRING Z ((262623.190 6652506.640 79.... 994 1 998 10.698588 MULTILINESTRING Z ((263489.330 6645655.330 11.... 995 1 999 10.109855 MULTILINESTRING Z ((269217.997 6650654.895 166... 996 1 1000 14.657289 MULTILINESTRING Z ((264475.675 6644245.782 114... [997 rows x 4 columns]
- get_route_frequencies(origins, destinations, weight_df=None, default_weight=None, rowwise=False, strict=False, frequency_col='frequency')[source]¶
Finds the number of times each line segment was visited in all trips.
Finds the route with the lowest cost (minutes, meters, etc.) from a set of origins to a set of destinations and summarises the number of times each segment was used. The aggregation is done on the line indices, which is much faster than getting the geometries and then dissolving.
The trip frequencies can be weighted (multiplied) based on ‘weight_df’. See example below.
- Parameters:
origins (
GeoDataFrame
) – GeoDataFrame of points from where the routes will originate.destinations (
GeoDataFrame
) – GeoDataFrame of points from where the routes will terminate.weight_df (
DataFrame
|None
) – A long formated DataFrame where each row contains the indices of an origin-destination pair and the number to multiply the frequency for this route by. The DataFrame can either contain three columns (origin index, destination index and weight. In that order) or only a weight column and a MultiIndex where level 0 is origin index and level 1 is destination index.default_weight (
int
|float
|None
) – If set, OD pairs not represented in ‘weight_df’ will be given a default weight value.rowwise (
bool
) – if False (default), it will calculate the cost from each origins to each destination. If true, it will calculate the cost from origin 1 to destination 1, origin 2 to destination 2 and so on.strict (
bool
) – If True, all OD pairs must be in weigth_df if specified. Defaults to False.frequency_col (
str
) – Name of column with the number of times each road was visited. Defaults to ‘frequency’.
- Return type:
GeoDataFrame
- Returns:
A GeoDataFrame with all line segments that were visited at least once, with a column with the number of times the line segment was used in the individual routes.
Note
The resulting lines will keep all columns of the ‘gdf’ of the Network.
- Raises:
ValueError – If weight_df is not a DataFrame with one or three columns that contain weights and all indices of ‘origins’ and ‘destinations’.
- Parameters:
origins (GeoDataFrame)
destinations (GeoDataFrame)
weight_df (DataFrame | None)
default_weight (int | float | None)
rowwise (bool)
strict (bool)
frequency_col (str)
- Return type:
GeoDataFrame
Examples:¶
Create the NetworkAnalysis instance.
>>> import sgis as sg >>> import pandas as pd >>> roads = sg.read_parquet_url("https://media.githubusercontent.com/media/statisticsnorway/ssb-sgis/main/tests/testdata/roads_oslo_2022.parquet") >>> directed_roads = sg.get_connected_components(roads).loc[lambda x: x["connected"] == 1].pipe(sg.make_directed_network_norway, dropnegative=True) >>> rules = sg.NetworkAnalysisRules(weight="minutes", directed=True) >>> nwa = sg.NetworkAnalysis(network=directed_roads, rules=rules, detailed_log=False)
Get some points.
>>> points = sg.read_parquet_url("https://media.githubusercontent.com/media/statisticsnorway/ssb-sgis/main/tests/testdata/points_oslo.parquet") >>> origins = points.iloc[:25] >>> destinations = points.iloc[25:50]
Get number of times each road was visited for trips from 25 to 25 points.
>>> frequencies = nwa.get_route_frequencies(origins, destinations) >>> frequencies[["source", "target", "frequency", "geometry"]] source target frequency geometry 160188 77264 79112 1.0 LINESTRING Z (268641.225 6651871.624 111.355, ... 153682 68376 4136 1.0 LINESTRING Z (268542.700 6652162.400 121.266, ... 153679 75263 75502 1.0 LINESTRING Z (268665.600 6652165.400 117.466, ... 153678 75262 75263 1.0 LINESTRING Z (268660.000 6652167.100 117.466, ... 153677 47999 75262 1.0 LINESTRING Z (268631.500 6652176.800 118.166, ... ... ... ... ... ... 151465 73801 73802 103.0 LINESTRING Z (265368.600 6647142.900 131.660, ... 151464 73800 73801 103.0 LINESTRING Z (265362.800 6647137.100 131.660, ... 151466 73802 73632 103.0 LINESTRING Z (265371.400 6647147.900 131.660, ... 151463 73799 73800 123.0 LINESTRING Z (265359.600 6647135.400 131.660, ... 152170 74418 74246 130.0 LINESTRING Z (264579.835 6651954.573 113.209, ... [8556 rows x 4 columns]
The frequencies can be weighted for each origin-destination pair by specifying ‘weight_df’. This can be a DataFrame with three columns, where the first two contain the indices of the origin and destination (in that order), and the third the number to multiply the frequency by. ‘weight_df’ can also be a DataFrame with a 2-leveled MultiIndex, where level 0 is the origin index and level 1 is the destination.
Constructing a DataFrame with all od-pair combinations and give all rows a weight of 10.
>>> od_pairs = pd.MultiIndex.from_product( ... [origins.index, destinations.index], names=["origin", "destination"] ... ) >>> weight_df = pd.DataFrame(index=od_pairs).reset_index() >>> weight_df["weight"] = 10 >>> weight_df origin destination weight 0 0 25 10 1 0 26 10 2 0 27 10 3 0 28 10 4 0 29 10 .. ... ... ... 620 24 45 10 621 24 46 10 622 24 47 10 623 24 48 10 624 24 49 10 [625 rows x 3 columns]
All frequencies will now be multiplied by 10.
>>> frequencies = nwa.get_route_frequencies(origins, destinations, weight_df, weight_df=weight_df) >>> frequencies[["source", "target", "frequency", "geometry"]] source target frequency geometry 160188 77264 79112 10.0 LINESTRING Z (268641.225 6651871.624 111.355, ... 153682 68376 4136 10.0 LINESTRING Z (268542.700 6652162.400 121.266, ... 153679 75263 75502 10.0 LINESTRING Z (268665.600 6652165.400 117.466, ... 153678 75262 75263 10.0 LINESTRING Z (268660.000 6652167.100 117.466, ... 153677 47999 75262 10.0 LINESTRING Z (268631.500 6652176.800 118.166, ... ... ... ... ... ... 151465 73801 73802 1030.0 LINESTRING Z (265368.600 6647142.900 131.660, ... 151464 73800 73801 1030.0 LINESTRING Z (265362.800 6647137.100 131.660, ... 151466 73802 73632 1030.0 LINESTRING Z (265371.400 6647147.900 131.660, ... 151463 73799 73800 1230.0 LINESTRING Z (265359.600 6647135.400 131.660, ... 152170 74418 74246 1300.0 LINESTRING Z (264579.835 6651954.573 113.209, ... [8556 rows x 4 columns]
‘weight_df’ can also be a DataFrame with one column (the weight) and a MultiIndex.
>>> weight_df = pd.DataFrame(index=od_pairs) >>> weight_df["weight"] = 10 >>> weight_df weight 0 25 10 26 10 27 10 28 10 29 10 ... ... 24 45 10 46 10 47 10 48 10 49 10 [625 rows x 1 columns]
- od_cost_matrix(origins, destinations, *, rowwise=False, destination_count=None, cutoff=None, lines=False)[source]¶
Fast calculation of many-to-many travel costs.
Finds the the lowest cost (minutes, meters, etc.) from a set of origins to a set of destinations. The index of the origins and destinations are used as values for the returned columns ‘origins’ and ‘destinations’.
- Parameters:
origins (
GeoDataFrame
) – GeoDataFrame of points from where the trips will originatedestinations (
GeoDataFrame
) – GeoDataFrame of points from where the trips will terminaterowwise (
bool
) – if False (default), it will calculate the cost from each origins to each destination. If true, it will calculate the cost from origin 1 to destination 1, origin 2 to destination 2 and so on.destination_count (
int
|None
) – number of closest destinations to keep for each origin. If None (default), all trips will be included. The number of destinations might be higher than the destination_count if trips have equal cost.cutoff (
int
|float
|None
) – the maximum cost (weight) for the trips. Defaults to None, meaning all rows will be included. NaNs will also be removed if cutoff is specified.lines (
bool
) – if True, returns a geometry column with straight lines between origin and destination. Defaults to False.
- Return type:
DataFrame
|GeoDataFrame
- Returns:
A DataFrame with the weight column and the columns ‘origin’ and ‘destination’, containing the indices of the origins and destinations GeoDataFrames. If lines is True, also returns a geometry column with straight lines between origin and destination.
Examples:¶
Create the NetworkAnalysis instance.
>>> import sgis as sg >>> roads = sg.read_parquet_url("https://media.githubusercontent.com/media/statisticsnorway/ssb-sgis/main/tests/testdata/roads_oslo_2022.parquet") >>> directed_roads = sg.get_connected_components(roads).loc[lambda x: x["connected"] == 1].pipe(sg.make_directed_network_norway, dropnegative=True) >>> rules = sg.NetworkAnalysisRules(weight="minutes", directed=True) >>> nwa = sg.NetworkAnalysis(network=directed_roads, rules=rules, detailed_log=False)
Create some origin and destination points.
>>> points = sg.read_parquet_url("https://media.githubusercontent.com/media/statisticsnorway/ssb-sgis/main/tests/testdata/points_oslo.parquet") >>> origins = points.loc[:99, ["geometry"]] >>> origins geometry 0 POINT (263122.700 6651184.900) 1 POINT (272456.100 6653369.500) 2 POINT (270082.300 6653032.700) 3 POINT (259804.800 6650339.700) 4 POINT (272876.200 6652889.100) .. ... 95 POINT (270348.000 6651899.400) 96 POINT (264845.600 6649005.800) 97 POINT (263162.000 6650732.200) 98 POINT (272322.700 6653729.100) 99 POINT (265622.800 6644644.200) [100 rows x 1 columns]
>>> destinations = points.loc[100:199, ["geometry"]] >>> destinations geometry 100 POINT (265997.900 6647899.400) 101 POINT (263835.200 6648677.700) 102 POINT (265764.000 6644063.900) 103 POINT (265970.700 6651258.500) 104 POINT (264624.300 6649937.700) .. ... 195 POINT (258175.600 6653694.300) 196 POINT (258772.200 6652487.600) 197 POINT (273135.300 6653198.100) 198 POINT (270582.300 6652163.800) 199 POINT (264980.800 6647231.300) [100 rows x 1 columns]
Travel time from 100 to 100 points.
>>> od = nwa.od_cost_matrix(origins, destinations) >>> od origin destination minutes 0 0 100 8.765621 1 0 101 6.383407 2 0 102 13.482324 3 0 103 6.410121 4 0 104 5.882124 ... ... ... ... 9995 99 195 20.488644 9996 99 196 16.721241 9997 99 197 19.977029 9998 99 198 15.233163 9999 99 199 6.439002 [10000 rows x 3 columns]
Assign aggregated values onto the origins (or destinations).
>>> origins["minutes_min"] = od.groupby("origin")["minutes"].min() >>> origins["minutes_mean"] = od.groupby("origin")["minutes"].mean() >>> origins["n_missing"] = len(origins) - od.groupby("origin")["minutes"].count() >>> origins geometry minutes_min minutes_mean n_missing 0 POINT (263122.700 6651184.900) 0.966702 11.628637 0 1 POINT (272456.100 6653369.500) 2.754545 16.084722 0 2 POINT (270082.300 6653032.700) 1.768334 15.304246 0 3 POINT (259804.800 6650339.700) 2.776873 14.044023 0 4 POINT (272876.200 6652889.100) 0.541074 17.565747 0 .. ... ... ... ... 95 POINT (270348.000 6651899.400) 1.529400 15.427027 0 96 POINT (264845.600 6649005.800) 1.336207 11.239592 0 97 POINT (263162.000 6650732.200) 1.010721 11.904372 0 98 POINT (272322.700 6653729.100) 3.175472 17.579399 0 99 POINT (265622.800 6644644.200) 1.116209 12.185800 0 [100 rows x 4 columns]
Join the results onto the ‘origins’ via the index.
>>> joined = origins.join(od.set_index("origin")) >>> joined geometry destination minutes 0 POINT (263122.700 6651184.900) 100 8.765621 0 POINT (263122.700 6651184.900) 101 6.383407 0 POINT (263122.700 6651184.900) 102 13.482324 0 POINT (263122.700 6651184.900) 103 6.410121 0 POINT (263122.700 6651184.900) 104 5.882124 .. ... ... ... 99 POINT (265622.800 6644644.200) 195 20.488644 99 POINT (265622.800 6644644.200) 196 16.721241 99 POINT (265622.800 6644644.200) 197 19.977029 99 POINT (265622.800 6644644.200) 198 15.233163 99 POINT (265622.800 6644644.200) 199 6.439002 [10000 rows x 3 columns]
Keep only travel times of 10 minutes or less. This is the same as using the cutoff parameter.
>>> ten_min_or_less = od.loc[od.minutes <= 10] >>> joined = origins.join(ten_min_or_less.set_index("origin")) >>> joined geometry destination minutes 0 POINT (263122.700 6651184.900) 100.0 8.765621 0 POINT (263122.700 6651184.900) 101.0 6.383407 0 POINT (263122.700 6651184.900) 103.0 6.410121 0 POINT (263122.700 6651184.900) 104.0 5.882124 0 POINT (263122.700 6651184.900) 106.0 9.811828 .. ... ... ... 99 POINT (265622.800 6644644.200) 173.0 4.305523 99 POINT (265622.800 6644644.200) 174.0 6.094040 99 POINT (265622.800 6644644.200) 177.0 5.944194 99 POINT (265622.800 6644644.200) 183.0 8.449906 99 POINT (265622.800 6644644.200) 199.0 6.439002 [2195 rows x 3 columns]
Keep the three fastest times from each origin. This is the same as using the destination_count parameter.
>>> three_fastest = od.loc[od.groupby("origin")["minutes"].rank() <= 3] >>> joined = origins.join(three_fastest.set_index("origin")) >>> joined geometry destination minutes 0 POINT (263122.700 6651184.900) 135.0 0.966702 0 POINT (263122.700 6651184.900) 175.0 2.202638 0 POINT (263122.700 6651184.900) 188.0 2.931595 1 POINT (272456.100 6653369.500) 171.0 2.918100 1 POINT (272456.100 6653369.500) 184.0 2.754545 .. ... ... ... 98 POINT (272322.700 6653729.100) 184.0 3.175472 98 POINT (272322.700 6653729.100) 189.0 3.179428 99 POINT (265622.800 6644644.200) 102.0 1.648705 99 POINT (265622.800 6644644.200) 134.0 1.116209 99 POINT (265622.800 6644644.200) 156.0 1.368926 [294 rows x 3 columns]
Use set_index to use column as identifier insted of the index.
>>> origins["areacode"] = np.random.choice(["0301", "3401"], len(origins)) >>> od = nwa.od_cost_matrix( ... origins.set_index("areacode"), ... destinations ... ) >>> od origin destination minutes 0 0301 100 8.765621 1 0301 101 6.383407 2 0301 102 13.482324 3 0301 103 6.410121 4 0301 104 5.882124 ... ... ... ... 9995 3401 195 20.488644 9996 3401 196 16.721241 9997 3401 197 19.977029 9998 3401 198 15.233163 9999 3401 199 6.439002 [10000 rows x 3 columns]
Travel time from 1000 to 1000 points rowwise.
>>> points_reversed = points.iloc[::-1] >>> od = nwa.od_cost_matrix(points, points_reversed, rowwise=True) >>> od origin destination minutes 0 0 999 14.692667 1 1 998 8.452691 2 2 997 16.370569 3 3 996 9.486131 4 4 995 16.521346 .. ... ... ... 995 995 4 16.794610 996 996 3 9.611700 997 997 2 19.968743 998 998 1 9.484374 999 999 0 14.892648 [1000 rows x 3 columns]
- precice_service_area(origins, breaks, *, dissolve=True)[source]¶
Precice, but slow version of the service_area method.
It finds all the network lines that can be reached within each break. Lines that are partly within the break will be split at the point where the weight value is exactly correct. Note that this takes more time than the regular ‘service_area’ method.
- Parameters:
origins (
GeoDataFrame
) – GeoDataFrame of points from where the service areas will originatebreaks (
int
|float
|tuple
[int
|float
]) – one or more integers or floats which will be the maximum weight for the service areas. Calculates multiple areas for each origins if multiple breaks.dissolve (
bool
) – If True (default), each service area will be dissolved into one long multilinestring. If False, the individual line segments will be returned.
- Return type:
GeoDataFrame
- Returns:
A GeoDataFrame with one row per break per origin, with a dissolved line geometry. If dissolve is False, it will return all the columns of the network.gdf as well.
See also
service_area: Faster method where lines are not cut to get precice results.
Examples:¶
Create the NetworkAnalysis instance.
>>> import sgis as sg >>> roads = sg.read_parquet_url("https://media.githubusercontent.com/media/statisticsnorway/ssb-sgis/main/tests/testdata/roads_oslo_2022.parquet") >>> directed_roads = sg.get_connected_components(roads).loc[lambda x: x["connected"] == 1].pipe(sg.make_directed_network_norway, dropnegative=True) >>> rules = sg.NetworkAnalysisRules(weight="minutes", directed=True) >>> nwa = sg.NetworkAnalysis(network=directed_roads, rules=rules, detailed_log=False)
10 minute service area for one origin point.
>>> points = sg.read_parquet_url("https://media.githubusercontent.com/media/statisticsnorway/ssb-sgis/main/tests/testdata/points_oslo.parquet")
>>> sa = nwa.precice_service_area( ... points.iloc[[0]], ... breaks=10, ... ) >>> sa idx minutes geometry 0 1 10 MULTILINESTRING Z ((264348.673 6648271.134 17....
Service areas of 5, 10 and 15 minutes from three origin points.
>>> sa = nwa.precice_service_area( ... points.iloc[:2], ... breaks=[5, 10, 15], ... ) >>> sa idx minutes geometry 0 1 5 MULTILINESTRING Z ((265378.000 6650581.600 85.... 1 1 10 MULTILINESTRING Z ((264348.673 6648271.134 17.... 2 1 15 MULTILINESTRING Z ((263110.060 6658296.870 154... 3 2 5 MULTILINESTRING Z ((273330.930 6653248.870 208... 4 2 10 MULTILINESTRING Z ((266909.769 6651075.250 114... 5 2 15 MULTILINESTRING Z ((264348.673 6648271.134 17....
- service_area(origins, breaks, *, dissolve=True)[source]¶
Returns the lines that can be reached within breaks (weight values).
It finds all the network lines that can be reached within each break. Lines that are only partly within the break will not be included. The index of the origins is used as values in the ‘origins’ column.
- Parameters:
origins (
GeoDataFrame
) – GeoDataFrame of points from where the service areas will originatebreaks (
int
|float
|tuple
[int
|float
]) – one or more integers or floats which will be the maximum weight for the service areas. Calculates multiple areas for each origins if multiple breaks.dissolve (
bool
) – If True (default), each service area will be dissolved into one long multilinestring. If False, the individual line segments will be returned.
- Return type:
GeoDataFrame
- Returns:
A GeoDataFrame with one row per break per origin, with the origin index and a dissolved line geometry. If dissolve is False, it will return each line that is part of the service area.
See also
precice_service_area: Equivelent method where lines are also cut to get precice results.
Examples:¶
Create the NetworkAnalysis instance.
>>> import sgis as sg >>> roads = sg.read_parquet_url("https://media.githubusercontent.com/media/statisticsnorway/ssb-sgis/main/tests/testdata/roads_oslo_2022.parquet") >>> directed_roads = sg.get_connected_components(roads).loc[lambda x: x["connected"] == 1].pipe(sg.make_directed_network_norway, dropnegative=True) >>> rules = sg.NetworkAnalysisRules(weight="minutes", directed=True) >>> nwa = sg.NetworkAnalysis(network=directed_roads, rules=rules, detailed_log=False)
10 minute service area for three origin points.
>>> points = sg.read_parquet_url("https://media.githubusercontent.com/media/statisticsnorway/ssb-sgis/main/tests/testdata/points_oslo.parquet") >>> service_areas = nwa.service_area( ... points.loc[:2], ... breaks=10, ... ) >>> service_areas origin minutes geometry 0 0 10 MULTILINESTRING Z ((264348.673 6648271.134 17.... 1 1 10 MULTILINESTRING Z ((266909.769 6651075.250 114... 2 2 10 MULTILINESTRING Z ((266909.769 6651075.250 114...
Service areas of 5, 10 and 15 minutes from three origin points.
>>> service_areas = nwa.service_area( ... points.iloc[:2], ... breaks=[5, 10, 15], ... ) >>> service_areas origin minutes geometry 0 0 5 MULTILINESTRING Z ((265378.000 6650581.600 85.... 1 0 10 MULTILINESTRING Z ((264348.673 6648271.134 17.... 2 0 15 MULTILINESTRING Z ((263110.060 6658296.870 154... 3 1 5 MULTILINESTRING Z ((273330.930 6653248.870 208... 4 1 10 MULTILINESTRING Z ((266909.769 6651075.250 114... 5 1 15 MULTILINESTRING Z ((264348.673 6648271.134 17....