寻求commandline工具:从CSV坐标列表中查找距离最近的点对
Python Command-Line Tool to Find Closest Point Pair from CSV Coordinates
Hey there! I’ve put together a Python command-line script that exactly addresses your need—finding the closest pair of points (not just each point’s nearest neighbor) from a CSV of geocoordinates, perfect for matching your GEO-sourced power plant data.
How It Works
This script uses the Haversine formula to calculate accurate great-circle distances between geographic points (Euclidean distance isn’t reliable for lat/long data). It checks all unique point pairs to pinpoint the minimum distance pair, with basic validation for messy CSV rows.
Full Script
Save this as closest_point_pair.py:
import csv import math import argparse def haversine(lat1, lon1, lat2, lon2): # Convert degrees to radians for trigonometric calculations lat1_rad = math.radians(lat1) lon1_rad = math.radians(lon1) lat2_rad = math.radians(lat2) lon2_rad = math.radians(lon2) # Haversine formula to compute great-circle distance dlon = lon2_rad - lon1_rad dlat = lat2_rad - lat1_rad a = math.sin(dlat/2)**2 + math.cos(lat1_rad) * math.cos(lat2_rad) * math.sin(dlon/2)**2 c = 2 * math.atan2(math.sqrt(a), math.sqrt(1-a)) # Earth radius in kilometers (use 3956 for miles) radius = 6371 return radius * c def find_closest_pair(csv_file): points = [] # Read and parse CSV data with open(csv_file, mode='r', newline='', encoding='utf-8') as f: reader = csv.reader(f) # Skip header (assumes CSV has columns: Name, Latitude, Longitude) next(reader) for row in reader: if len(row) >= 3: name = row[0].strip() try: lat = float(row[1]) lon = float(row[2]) points.append( (name, lat, lon) ) except ValueError: print(f"Skipping invalid row (non-numeric coordinates): {row}") if len(points) < 2: print("Error: Need at least two points to find a closest pair.") return min_distance = float('inf') closest_pair = None # Check all unique point pairs to find the smallest distance for i in range(len(points)): name1, lat1, lon1 = points[i] for j in range(i+1, len(points)): name2, lat2, lon2 = points[j] distance = haversine(lat1, lon1, lat2, lon2) if distance < min_distance: min_distance = distance closest_pair = (name1, name2, lat1, lon1, lat2, lon2) if closest_pair: name1, name2, lat1, lon1, lat2, lon2 = closest_pair print("✅ Closest pair found:") print(f"- {name1} | Lat: {lat1}, Lon: {lon1}") print(f"- {name2} | Lat: {lat2}, Lon: {lon2}") print(f"Distance: {round(min_distance, 4)} kilometers") if __name__ == "__main__": parser = argparse.ArgumentParser(description='Find the closest pair of geographic points from a CSV file.') parser.add_argument('csv_file', help='Path to your CSV file (columns: Name, Latitude, Longitude)') args = parser.parse_args() find_closest_pair(args.csv_file)
Usage Instructions
- Prepare your CSV: Ensure your file follows this structure (comma-delimited):
Name,Latitude,Longitude Chicoasén Dam,16.941064,-93.100828 Tuxpan Oil Power Plant,21.014891,-97.3344 Coastal Generator,16.950000,-93.090000
- Run the script: Open your terminal and run:
python closest_point_pair.py your_power_plants.csv
- Adjust units: If you need miles instead of kilometers, change the
radiusvalue in thehaversinefunction from6371to3956.
Key Notes
- Validation: The script skips rows with non-numeric coordinates and alerts you to invalid entries.
- Performance: This brute-force approach works great for most power plant datasets (hundreds to thousands of points). For extremely large datasets (10k+ points), you could upgrade to a divide-and-conquer algorithm, but that’s overkill for typical use cases here.
- Custom delimiters: If your CSV uses tabs or semicolons, modify the
csv.readercall to includedelimiter='\t'ordelimiter=';'.
内容的提问来源于stack exchange,提问作者pickenpack
相关产品推荐
相关产品推荐

