GIS & Geospatial Data (QGIS, GeoPandas, PostGIS) Module 5
Python: Shapely and GeoPandas interview questions
Interview questions on “Python: Shapely and GeoPandas”: warm-ups, then what each harder question tests and how a good answer starts.
Warm-up questions
Short questions with short answers, each answered in full.
-
Fresher
Shapely has no coordinate reference system. What does that mean for point.buffer(1000)?
Answered in the lesson Shapely 2: geometry operations in Python
-
Fresher
What is the difference between within and covered_by for a point on a polygon's edge?
Answered in the lesson Spatial joins: predicates, nearest and CRS traps
-
Fresher
What is the difference between clip and an intersection overlay?
Answered in the lesson Overlay, dissolve, clip and areal weighting
-
Fresher
What does a spatial index store, and why does a query still need an exact test?
Answered in the lesson Spatial indexes: R-trees, sindex and fast joins
-
Fresher
Why can a PIN code not stand in for a household's location?
Answered in the lesson Geocoding, Indian addresses and DIGIPIN
-
Fresher
What is an isochrone, and why is it not a circle?
Answered in the lesson Street networks, routing and isochrones
Questions with model answers
What each question tests, the first step of a good answer and the follow-ups to expect.
-
Fresher to mid
A coverage report counts the households inside the union of 1 km buffers around 8 clinics and finds 2,971. A distance query on the same data finds 2,973 households within 1,000 m of a clinic. Explain the difference, say which number you would publish, and how you would make the pipeline give one answer.
- What it tests
- Knowing that a buffer is an inscribed polygon, choosing an exact method for distance questions, and designing a pipeline whose area and count agree by construction.
- First step
- Ask how the buffers were made. A buffer is a polygon whose corners lie on the circle, 64 sides by default for the geometry's method, so it covers slightly less than the true 1 km disc. Find the two households: they are within 1,000 m of a clinic but outside the polygon, in the slivers between its sides and the circle.
- Follow-ups
-
- How much area does a 64-sided buffer lose, and how does the loss change with quad_segs?
- The report also gives the covered area. Should that come from the buffers or from the distances?
- How would you test the pipeline so that the two numbers never disagree again?
From the lesson Shapely 2: geometry operations in Python
Model answer, Pro. Model answers open with any pass; prices are in the notice on this page.Opening the model answers with your pass…
Model answers open with any MySmartCoPilot pass.
- Pro pass · 1 week₹79$2.99
- 30 days₹179$5.99
- 1 year₹1,699$45
One payment; a pass never renews. The price shown is the total you pay: no fees or charges are added at checkout.
Passes can’t be bought right now, so the model answers can’t be opened at the moment. If you have a pass, enter your licence key.
It also opens every other in-depth part in Learn and every Pro tool. Sales are final, except where the law gives you a right to withdraw, for example in the EU and the UK (refund policy).
In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Mid to senior
A regression test compares the WKT of a dissolved zone with a stored string. After a dependency upgrade the test fails in CI, although the maps look identical and nobody changed the code. What do you suspect, how do you confirm it, and how should the test be written?
- What it tests
- Understanding that GEOS does the geometry and its version can change descriptions without changing shapes, and writing geometry tests that compare shapes rather than text.
- First step
- Compare the versions first: print shapely.__version__ and shapely.geos_version_string in both environments. A new Shapely wheel brings a new GEOS, and GEOS may return the same polygon from another start vertex, in the other direction, or with extra vertices on straight edges. Then check shapely.equals(old, new) and the two areas.
- Follow-ups
-
- The areas differ by 0.000002 m². Is that a bug?
- Why might the same test also fail in a browser build of the same Shapely version?
- When is comparing exact coordinates the right test after all?
From the lesson Shapely 2: geometry operations in Python
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Fresher to mid
A partner's GeoPackage of 12 wards says EPSG:32643. Transformed to WGS 84 for a web map, all 12 wards collapse into a speck in the Indian Ocean at about 70.5° E, on the equator. What is wrong with the file, how do you prove it, and how do you fix it?
- What it tests
- Telling a wrong CRS label from wrong coordinates, reading bounds against a CRS's units and area of use, and choosing set_crs or to_crs for the fix.
- First step
- Print the layer's total bounds before any transform. If they read like 75.02 to 75.04 and 18.12 to 18.14, the numbers are degrees, while the label says metres of UTM zone 43N: an easting of 75 m lies about 500 km west of the zone's central meridian, which is where the transform put it.
- Follow-ups
-
- Which single line fixes the file, and why is to_crs the wrong tool for it?
- How would a check in your import pipeline have caught this automatically?
- What would you tell the partner, so that the next delivery is right?
From the lesson GeoDataFrames: reading, writing and CRS
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Mid to senior
A nightly job reads households with read_file and a bounding box per district. Since a new web form started supplying the boxes, one district reports 0 households where it had 696. Nothing raised an error. Explain what happened, and how you would make the job both correct and loud when it goes wrong.
- What it tests
- Reading filters together with the CRS of the data they filter, and designing guards for silent empty results.
- First step
- Compare the box's numbers with the layer's bounds and CRS. A web form most likely sends longitude and latitude, while the households layer is in metres of UTM zone 43N. Then ask what a bounding box knows about its own CRS, and what read_file does with four numbers it cannot place.
- Follow-ups
-
- Would a mask in EPSG:4326 have failed the same way as the box, and why?
- What check would have stopped the report going out with a zero?
- How do you test the job so this cannot come back?
From the lesson GeoDataFrames: reading, writing and CRS
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Fresher to mid
One wards layer, in metres of UTM zone 43N with int64 household counts, must reach a web map, a desktop GIS team and a data scientist's notebook. Which format and options do you send to each, and what do you check before sending?
- What it tests
- Matching formats to receivers by what each keeps (CRS, types, layers, web readability) and verifying a written file by reading it back.
- First step
- List what each receiver needs. The web map needs a file a browser can parse, in WGS 84: RFC 7946 GeoJSON. The GIS team needs the CRS and types intact, perhaps with other layers: a GeoPackage. The notebook wants fast, typed columns: GeoParquet. Then write each, read it back and compare.
- Follow-ups
-
- What does the GeoJSON lose, and is that acceptable for the web map?
- The GIS team also wants the ward centres. How do you send them?
- Which three things do you compare after reading each file back?
From the lesson GeoDataFrames: reading, writing and CRS
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Fresher to mid
A report of households per ward, built with sjoin and predicate="intersects", adds up to 5,037 although the survey has 5,000 households. Nothing failed. What happened, how do you find the households involved, and how do you fix the report so that it cannot happen again?
- What it tests
- Recognising double counts from points on shared boundaries or from overlapping polygons, finding them through duplicate keys, and enforcing a one-match rule with a total check.
- First step
- Look for households that appear in more than one row of the join:
joined["household"].duplicated(keep=False). Each one matched two wards. Then ask why: a point exactly on a shared edge intersects both wards, as clinic C2 does, and so does a point where two ward polygons overlap because they were digitised separately. - Follow-ups
-
- The 37 duplicates all have coordinates rounded to 10 m. Why does that matter?
- How do you tell a boundary point from a point in an overlap of two wards?
- Which check would have stopped the report?
From the lesson Spatial joins: predicates, nearest and CRS traps
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Mid to senior
A coverage report computes the share of households within 1.5 km of a clinic from sjoin_nearest with max_distance=1500, and it says 100 %. Field teams know of households much farther away. Find the bug, give the correct share for the lesson's town, and describe how you would rebuild the report.
- What it tests
- Understanding what a distance limit does to rows without a match, computing shares over the right denominator, and handling ties and limits deliberately.
- First step
- Count the rows the join returned and compare them with the number of households in the survey. If they differ, trust nothing about the share until you know which households are missing from the join, and why a share computed over the rows that remain cannot be anything but 100 %.
- Follow-ups
-
- How do the ties between clinics change the counts, and what do you do about them?
- Why is a straight-line distance still optimistic, and what would you use instead?
- What should the report show about the households without a clinic?
From the lesson Spatial joins: predicates, nearest and CRS traps
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Fresher to mid
A notebook joins 5,000 survey points to the town's wards and every ward shows 0 households. No error appeared and the code worked last week with another file. How do you find the cause, and what do you add so that the notebook fails loudly next time?
- What it tests
- Diagnosing an empty join from CRS mismatches, swapped axes or wrong layers, reading warnings, and adding guards that turn silent failures into errors.
- First step
- Print the CRS and the total bounds of both layers, and reread every warning the notebook printed. Points around 75° and 18° and wards around 500,000 m east cannot meet, whatever the predicate.
- Follow-ups
-
- The CRSs are equal, and the join is still empty. What else would you check?
- Why is a warning not enough in a pipeline?
- How would you write a test for the guard?
From the lesson Spatial joins: predicates, nearest and CRS traps
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Fresher to mid
Census blocks with households and a density column are dissolved into wards with aggfunc={"households": "sum", "density": "mean"}. A ward of 4 km² holds 1,169 households, yet its density comes out well below what those two numbers give. What is wrong, what is the right density, and how do you set up the dissolve?
- What it tests
- Choosing an aggregation rule per column, telling counts from rates, and knowing dissolve's default.
- First step
- Check the density against its own parts: divide the ward's households by its area and compare. Then ask how a mean of the blocks' densities treats two blocks of very different sizes.
- Follow-ups
-
- What would the report show without any aggfunc at all?
- Which other kinds of column must not be averaged, and which may?
- How would you test a dissolve step?
From the lesson Overlay, dissolve, clip and areal weighting
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 2 minutes
-
Mid to senior
A health department has households per census block and needs households per clinic catchment, whose boundaries cross the blocks. Describe how you would estimate them, how wrong the estimates can be, and how you would report them honestly.
- What it tests
- Areal weighting built from an overlay, its even-spread assumption, measuring its error where truth exists, and better methods with ancillary data.
- First step
- Overlay the blocks with the catchments, give each piece the block's count times the piece's share of the block's area, and sum the pieces per catchment. Then compare the catchment totals with the census total.
- Follow-ups
-
- On the lesson's town, how large were the errors, and which catchment fared worst, and why?
- How would you reduce the error without new survey data?
- What do you write next to the numbers in the report?
From the lesson Overlay, dissolve, clip and areal weighting
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 2 minutes
-
Mid to senior
A notebook assigns 2 million delivery points to 9,000 wards by looping over every pair in Python and calling ward.contains(point). It has run for hours. How do you make it fast, how long should the new version take, and how do you show that its answer did not change?
- What it tests
- Estimating work from counts, replacing a loop over pairs with one indexed join, and proving that a faster rewrite gives the same result.
- First step
- Count the work first: 2 million points times 9,000 wards is 18 billion exact tests, one Python call each. An indexed join tests each point only against the wards whose boxes it falls in, usually one or two, so the exact tests drop to a few million and the calls to one.
- Follow-ups
-
- Some points lie exactly on a ward boundary. What happens to them?
- The wards arrive as one MultiPolygon per district. Does that change the plan?
- How do you check the rewrite without waiting hours for the old version?
From the lesson Spatial indexes: R-trees, sindex and fast joins
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Mid to senior
Finding the buildings inside a state's floodplain takes minutes, although the buildings layer has a spatial index. The floodplain is one MultiPolygon of 400,000 vertices along every river of the state. Why is the index not helping, and what do you change?
- What it tests
- Seeing that a large shape's bounding box defeats the first step, and restoring small boxes by exploding and subdividing instead of simplifying.
- First step
- Look at the floodplain's bounding box: one box around every river of a state covers most of the state, so nearly every building becomes a candidate, and each candidate is tested against a polygon of 400,000 vertices. Compare the number of candidates with the number of buildings inside.
- Follow-ups
-
- Would simplifying the floodplain by 50 m be an acceptable fix?
- How many vertices should each piece have?
- The same query runs in PostGIS. What do you do there?
From the lesson Spatial indexes: R-trees, sindex and fast joins
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Senior to staff
In PostGIS, a query with WHERE ST_Distance(geom, :p) < 500 reads the whole 20-million-row table, although geom has a GiST index. Explain what the planner sees, how you confirm it and how you rewrite the query. After a bulk load, the rewritten query is slow again: what next?
- What it tests
- Knowing which conditions an index can serve, reading EXPLAIN output, and how statistics steer the planner's choice of plan.
- First step
- Run EXPLAIN and read the scan node: a Seq Scan with a filter on st_distance means the index was never searched. Then ask which questions a GiST index of bounding boxes can answer, and whether a distance compared with a number is one of them.
- Follow-ups
-
- What does the plan look like after the rewrite, and which line is the exact test?
- The column is geography, not geometry. Does anything change?
- Why might the planner still read the whole table for a radius of 50 km?
From the lesson Spatial indexes: R-trees, sindex and fast joins
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Fresher to mid
A health department geocodes 3,000 clinic addresses for a coverage map, and 412 clinics land on exactly the same point in the middle of the district town. Nothing failed. What happened, how do you find every affected clinic, and what do you do about them?
- What it tests
- Recognising coarse fallback matches, finding them from the rank and from repeated coordinates, and handling addresses without a good match honestly.
- First step
- Look at the answers those 412 rows got. They probably share a low place_rank, 18 or below, the rank of a town or a city: the geocoder could not match the street and fell back to the town's centre. Group the results by coordinate and by rank, and list every answer below street level.
- Follow-ups
-
- Some of the 412 have a PIN code. Can you use it to place them?
- How would you set the threshold for an acceptable answer?
- What should the coverage map show for the clinics without a good match?
From the lesson Geocoding, Indian addresses and DIGIPIN
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Mid to senior
A delivery app stores the DIGIPIN of each customer's door, made from the phone's position at sign-up. Riders report that many parcels go to the neighbour's gate. Explain why, and redesign what the app stores and how it uses it.
- What it tests
- Relating a code's cell size to the error of the position it came from, and designing storage that keeps the accuracy and lets a wrong point be corrected.
- First step
- Compare two sizes. A full DIGIPIN cell is about 4 m across, and a phone outdoors is often several metres off, more between tall buildings. Ask which code a position gets when the fix lands a few metres from the door, and what the rider then sees.
- Follow-ups
-
- Would storing only the first 8 symbols help?
- How do you let the customer correct the point?
- What would you index to find the orders near a rider?
From the lesson Geocoding, Indian addresses and DIGIPIN
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
-
Mid to senior
You must geocode 200,000 addresses once, for a public dashboard. A colleague proposes a script that calls the public Nominatim service from ten threads, to finish overnight. What do you tell them, and what plan do you propose instead?
- What it tests
- Knowing a public geocoder's usage policy and licence, estimating a job's time from its rate limit, and choosing a source that suits the volume.
- First step
- Check the plan against the usage policy: one request a second from one thread on one machine, bulk geocoding discouraged, and 4 a minute for scripts that run longer than a day. Ten threads break the first rule at once; then work out how long a single thread would take, and which limit applies to it.
- Follow-ups
-
- How would you run your own instance, and what does it need?
- What does the ODbL ask of a dashboard that publishes the results?
- How do you check the quality of 200,000 answers?
From the lesson Geocoding, Indian addresses and DIGIPIN
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 2 minutes
-
Fresher to mid
A district report says 2,973 of the town's 5,000 households live within 1 km of a clinic, from 1 km buffers round the 8 clinics. Residents south of the river say they walk much further. How do you check the claim, and what figure would you report instead?
- What it tests
- Seeing that buffers measure straight lines, computing coverage along the network from all clinics at once, and reporting the method beside the figure.
- First step
- Ask what the 1 km is measured along. A buffer counts every household within 1 km in a straight line, across the river and through blocks. Recompute along the street network: one run of Dijkstra's algorithm from all 8 clinics at once gives every junction its walk to the nearest clinic.
- Follow-ups
-
- How do you place the households on the network?
- Which households change their nearest clinic, and why?
- What should the report say about its method?
From the lesson Street networks, routing and isochrones
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 2 minutes
-
Mid to senior
A delivery app's routes look short on the map, but drivers say they are slow. A colleague finds that the router was called with its default settings. What do you check, and how do you make the routes fast?
- What it tests
- Knowing that routers often minimise length by default, deriving time weights from speeds and tags, and checking travel times against measured ones.
- First step
- Check which weight the router minimised. OSMnx's shortest_path minimises length unless told otherwise, so it returns the shortest route, often through slow streets. Add speeds and travel times to the edges, route by travel time, and compare a sample of routes with drivers' recorded times.
- Follow-ups
-
- Where do the speeds come from, and what if a street has no maxspeed tag?
- The fastest route is 2 km longer. Is it worth it?
- How do one-way streets enter the graph?
From the lesson Street networks, routing and isochrones
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 2 minutes
-
Senior to staff
A state plans ambulance bases so that 90 % of villages are within 30 minutes by road. The first analysis routes on OpenStreetMap roads at posted speeds, at all hours. What would you add before trusting the result, and how would you present its uncertainty?
- What it tests
- Knowing what a simple road graph leaves out, checking a network before routing, and presenting coverage as a range with its assumptions.
- First step
- List what the graph leaves out and what each does to the times: turn restrictions, speeds by hour, road condition, missing roads and ferries. Then ask how you would know whether the road data itself has gaps, before any time is trusted.
- Follow-ups
-
- How would you model the morning peak?
- Some villages are 3 km from the nearest mapped road. What do you do?
- What does the ODbL ask if the bases' isochrones are published as data?
From the lesson Street networks, routing and isochrones
Model answer, Pro.In the answer:
- Model answer
- Follow-up answers
- Common mistakes
- Rubric
- Variants
- about 3 minutes
All GIS & Geospatial Data (QGIS, GeoPandas, PostGIS) interview questions · The GIS & Geospatial Data (QGIS, GeoPandas, PostGIS) track