Accessing a World Port Database using Python

Jordan Taylor
Shipping Intel
Published in
5 min readAug 22, 2023

Co-authored by Aurora Thomas.

The United States National Geospatial Agency’s World Port Index (WPI) contains the location, physical characteristics, and services offered by major ports and terminals worldwide. Deployed by the agency as a comma separated value (CSV) file, a method of extracting port information using Python is offered for consideration. The effort will allow the data found in the WPI to be combined with other maritime data points to support maritime risk assessments.

Source: National Geospatial Agency

Introduction

The United States National Geospatial Agency’s World Port Index is a collection of 3,818 world ports and is updated monthly. Each port contains 106 data points that contain information such as port coordinates, entrance requirements, and minimum allowable draft. An explanation of each WPI data field can be found in the World Port Index Explanation of Data Fields.

Typically when a vessel enters a port a local agent, and not the WPI dataset, is employed to provide up-to-date port information for vessel arrival. The agent, who is experienced in locating information within a port, is the only reliable method for vessel operators to understand port particulars. However, the WPI data can be used for initial appraisal and when combined with other maritime data can serve to support supply chain transparency.

Method

Step 1: Obtain the World Port Index Comma Separated Value (CSV) File

Download the file UpdatedPub150.csv via the National Geospatial Agency Maritime Safety Information website.

Step 2: Import Required Packages

import csv
from fuzzywuzzy import process

Step 3: Establish a File Path

csv_file = "UpdatedPub150.csv"

Step 4: Obtain Query Values as a List

In this example, we will search using the port name. Therefore, a list of port names must be obtained in order to find the best match. The WPI file contains the port names in column index two.

with open(csv_file, "r") as file:
reader = csv.reader(file)
column_values = [row[2] for row in reader]

Step 5: Employ Natural Language Processing

Fuzzywuzzy is employed to find the best match to the port name entering argument. This is done because the spelling of the port as entered may not exactly match the port within the WPI list of ports.

For this example we will use the port of San Francisco in lower case.

port_to_match = "san francisco"
best_match = process.extractOne(port_to_match, column_values)

Step 6: Match the Port with Row Data

A search of the match will then be conducted on the WPI, and the data extracted as a key:value pair.

with open(csv_file, "r") as file:
reader = csv.DictReader(file)
for row in reader:
if row['Main Port Name'] == best_match[0]:
port_information = dict(row)

Result

The outcome, expressed as a Python dictionary, will appear as follows:

{'World Port Index Number': '16300', 'Region Name': 'United States W Coast -- 16000', 'Main Port Name': 'San Francisco', 'Alternate Port Name': ' ', 'UN/LOCODE': 'US SFO', 'Country Code': 'United States', 'World Water Body': 'North Pacific Ocean', 'IHO S-130 Sea Area': ' ', 'Sailing Direction or Publication': 'U.S. Coast Pilot 7 - Pacific Coast: California', 'Publication Link': 'https://nauticalcharts.noaa.gov/publications/coast-pilot/files/cp7/CPB7_WEB.pdf', 'Standard Nautical Chart': '18650', 'Digital Nautical Chart': 'coa13b, gen13a, h1316300', 'Tidal Range (m)': '1.2', 'Entrance Width (m)': '0', 'Channel Depth (m)': '9.4', 'Anchorage Depth (m)': '7.9', 'Cargo Pier Depth (m)': '11', 'Oil Terminal Depth (m)': '11', 'Liquified Natural Gas Terminal Depth (m)': '0', 'Maximum Vessel Length (m)': '0', 'Maximum Vessel Beam (m)': '0', 'Maximum Vessel Draft (m)': '0', 'Offshore Maximum Vessel Length (m)': '0', 'Offshore Maximum Vessel Beam (m)': '0', 'Offshore Maximum Vessel Draft (m)': '0', 'Harbor Size': 'Large', 'Harbor Type': 'Coastal (Natural)', 'Harbor Use': 'Unknown', 'Shelter Afforded': 'Excellent', 'Entrance Restriction - Tide': 'No', 'Entrance Restriction - Heavy Swell': 'No', 'Entrance Restriction - Ice': 'No', 'Entrance Restriction - Other': 'Yes', 'Overhead Limits': 'Yes', 'Underkeel Clearance Management System': 'Unknown', 'Good Holding Ground': 'Unknown', 'Turning Area': 'Yes', 'Port Security': 'Unknown', 'Estimated Time of Arrival Message': 'Yes', 'Quarantine - Pratique': 'Yes', 'Quarantine - Sanitation': 'Yes', 'Quarantine - Other': 'Yes', 'Traffic Separation Scheme': 'Unknown', 'Vessel Traffic Service': 'Unknown', 'First Port of Entry': 'Yes', 'US Representative': 'Yes', 'Pilotage - Compulsory': 'Yes', 'Pilotage - Available': 'Yes', 'Pilotage - Local Assistance': 'Unknown', 'Pilotage - Advisable': 'Yes', 'Tugs - Salvage': 'Yes', 'Tugs - Assistance': 'Yes', 'Communications - Telephone': 'Yes', 'Communications - Telefax': 'Yes', 'Communications - Radio': 'Yes', 'Communications - Radiotelephone': 'Yes', 'Communications - Airport': 'Yes', 'Communications - Rail': 'Yes', 'Search and Rescue': 'Unknown', 'NAVAREA': 'XII', 'Facilities - Wharves': 'Yes', 'Facilities - Anchorage': 'Yes', 'Facilities - Dangerous Cargo Anchorage': 'Unknown', 'Facilities - Med Mooring': 'Unknown', 'Facilities - Beach Mooring': 'Unknown', 'Facilities - Ice Mooring': 'Unknown', 'Facilities - Ro-Ro': 'Unknown', 'Facilities - Solid Bulk': 'Unknown', 'Facilities - Liquid Bulk': 'Unknown', 'Facilities - Container': 'Unknown', 'Facilities - Breakbulk': 'Unknown', 'Facilities - Oil Terminal': 'Unknown', 'Facilities - LNG Terminal': 'Unknown', 'Facilities - Other': 'Unknown', 'Medical Facilities': 'Yes', 'Garbage Disposal': 'Yes', 'Chemical Holding Tank Disposal': 'Unknown', 'Degaussing': 'Yes', 'Dirty Ballast Disposal': 'Yes', 'Cranes - Fixed': 'Yes', 'Cranes - Mobile': 'Yes', 'Cranes - Floating': 'Yes', 'Cranes - Container': 'Unknown', 'Lifts - 100+ Tons': 'Yes', 'Lifts - 50-100 Tons': 'Unknown', 'Lifts - 25-49 Tons': 'Unknown', 'Lifts - 0-24 Tons': 'Unknown', 'Services - Longshoremen': 'Yes', 'Services - Electricity': 'Yes', 'Services - Steam': 'Yes', 'Services - Navigation Equipment': 'Yes', 'Services - Electrical Repair': 'Yes', 'Services - Ice Breaking': 'Unknown', 'Services - Diving': 'Unknown', 'Supplies - Provisions': 'Yes', 'Supplies - Potable Water': 'Yes', 'Supplies - Fuel Oil': 'Yes', 'Supplies - Diesel Oil': 'Yes', 'Supplies - Aviation Fuel': 'Unknown', 'Supplies - Deck': 'Yes', 'Supplies - Engine': 'Yes', 'Repairs': 'Major', 'Dry Dock': 'Medium', 'Railway': 'Large', 'Latitude': '37.816667', 'Longitude': '-122.416667'}

Examples of the data above is an anchorage depth of 7.9 meters, a channel depth of 9.4 meters, latitude of 37.81° N, longitude of 122.41° W, and a list of applicable electronic nautical charts (ENCs).

Final Code Example

The final code is rendered as a function.

import csv
from fuzzywuzzy import process

def world_port_index(port_to_match):

# Establish a File Path from Local Directory
# Location of original file: https://msi.nga.mil/Publications/WPI
csv_file = "UpdatedPub150.csv"

# Obtain Query Values as a List
with open(csv_file, "r") as file:
reader = csv.reader(file)
column_values = [row[2] for row in reader]

# Natural Language Processing
best_match = process.extractOne(port_to_match, column_values)

# Match the Port with the Row Data
with open(csv_file, "r") as file:
reader = csv.DictReader(file)
for row in reader:
if row['Main Port Name'] == best_match[0]:
port_information = dict(row)

return port_information

Conclusion

The World Port Index is limited in practical use. For example, the dataset in the above example for San Francisco lists the draft of oil terminals as 11 meters. This figure does not factor in specific terminals, under keel clearance (UKC) requirements, or water density.

The WPI data should always be compared to up-to-date agency information.

However, when used with bulk data such as the trade flows of very large crude carriers (VLCCs) whose draft may exceed 20 meters, the data could used to narrow the ports that such vessels could access. The data could further be sorted by parameters other than the port name. For example, a vessel position or future position could be georeferenced to the WPI coordinate data. This might be effective for voyage appraisal, in order to help operators gain insight for further planning.

References

Cohen, A. (n.d.). Fuzzywuzzy. PyPI. Retrieved August 18, 2023, from https://pypi.org/project/fuzzywuzzy/

Maritime Safety Information. (n.d.). Maritime Safety Information. Retrieved August 18, 2023, from https://msi.nga.mil/Publications/WPI

World Port Index Explanation of Data Fields. (n.d.). Maritime Safety Information. Retrieved August 18, 2023, from https://msi.nga.mil/api/publications/download?key=16920959/SFH00000/WPI_Explanation_of_Data_Fields.pdf&type=view

--

--

Jordan Taylor
Shipping Intel

Merchant marine officer with a B.S. in Marine Transportation and a M.S. in Transportation Management.