קידוד גיאוגרפי עבור מדעני נתונים - KDnuggets

קידוד גיאוגרפי עבור מדעני נתונים - KDnuggets

צומת המקור: 2713218

כאשר מדעני נתונים צריכים לדעת כל מה שצריך לדעת על ה"איפה" של הנתונים שלהם, הם פונים לעתים קרובות למערכות מידע גיאוגרפיות (GIS). GIS הוא קבוצה מסובכת של טכנולוגיות ותוכניות המשרתות מגוון רחב של מטרות, אך אוניברסיטת וושינגטון מספקת הגדרה מקיפה למדי, ואומרת "מערכת מידע גיאוגרפית היא סידור מורכב של דברים או אובייקטים קשורים או מחוברים, שמטרתם היא להעביר ידע על תכונות על פני כדור הארץ" (Lawler et al). GIS מקיף מגוון רחב של טכניקות לעיבוד נתונים מרחביים מרכישה ועד להדמיה, שרבים מהם הם כלים חשובים גם אם אינך מומחה GIS. מאמר זה מספק סקירה מקיפה של קידוד גיאוגרפי עם הדגמות ב-Python של מספר יישומים מעשיים. באופן ספציפי, תקבע את המיקום המדויק של פיצה בניו יורק, ניו יורק באמצעות הכתובת שלו ותחבר אותו לנתונים על פארקים סמוכים. בעוד שההדגמות משתמשות בקוד Python, ניתן ליישם את מושגי הליבה בסביבות תכנות רבות כדי לשלב קידוד גיאוגרפי בזרימת העבודה שלך. כלים אלו מספקים את הבסיס להפיכת נתונים לנתונים מרחביים ופותחים את הדלת לניתוח גיאוגרפי מורכב יותר. 

 

XXXXX

קידוד גיאוגרפי מוגדר לרוב כהפיכת נתוני כתובת לקואורדינטות מיפוי. בדרך כלל, זה כרוך בזיהוי שם רחוב בכתובת, התאמת רחוב זה לגבולות המקביל שלו בעולם האמיתי במסד נתונים, ואז הערכת היכן ברחוב למקם את הכתובת באמצעות מספר הרחוב. כדוגמה, בואו נעבור על תהליך של קוד גיאוגרפי פשוט לכתובת של פיצה בניו יורק בברודווי: 2709 Broadway, New York, NY 10025. המשימה הראשונה היא מציאת קבצי צורה מתאימים למערכת הדרכים של המיקום של הכתובת שלך. שים לב שבמקרה זה העיר ומדינת הכתובת הן "ניו יורק, ניו יורק". למרבה המזל, העיר ניו יורק מפרסמת מידע מפורט על הכביש נתונים פתוחים של ניו יורק עמוד (CSCL PUB). שנית, בחנו את שם הרחוב "ברודווי". כעת אתה יודע שהכתובת יכולה להיות בכל רחוב שנקרא "Broadway" בעיר ניו יורק, כך שתוכל להפעיל את קוד ה-Python הבא כדי לשאול את NYC Open Data SODA API עבור כל הרחובות בשם "Broadway".

import geopandas as gpd
import requests
from io import BytesIO # Request the data from the SODA API
req = requests.get( "https://data.cityofnewyork.us/resource/gdww-crzy.geojson?stname_lab=BROADWAY"
)
# Convert to a stream of bytes
reqstrm = BytesIO(req.content)
# Read the stream as a GeoDataFrame
ny_streets = gpd.read_file(reqstrm)

 

יש יותר מ-700 תוצאות של השאילתה הזו, אבל זה לא אומר שאתה צריך לבדוק 700 רחובות כדי למצוא את הפיצה שלך. בהתחשב בנתונים, אתה יכול לראות שיש 3 רחובות ראשיים בברודווי וכמה קטנים יותר.

 

XXXXX
 

הסיבה לכך היא שכל רחוב מחולק למקטעים התואמים בערך לבלוק, מה שמאפשר מבט מפורט יותר על הנתונים. השלב הבא של התהליך הוא קביעת בדיוק באיזה מקטעים אלו נמצאת הכתובת באמצעות המיקוד ומספר הרחוב. כל קטע רחוב במערך הנתונים מכיל טווחי כתובות עבור הכתובות של בניינים הן בצד שמאל והן בצד ימין של הרחוב. באופן דומה, כל קטע מכיל את המיקוד הן בצד שמאל והן בצד ימין של הרחוב. כדי לאתר את הקטע הנכון, הקוד הבא מחיל מסננים כדי למצוא את קטע הרחוב שהמיקוד שלו תואם את המיקוד של הכתובת ושטווח הכתובות שלו מכיל את מספר הרחוב של הכתובת.

# Address to be geocoded
address = "2709 Broadway, New York, NY 10025"
zipcode = address.split(" ")[-1]
street_num = address.split(" ")[0] # Find street segments whose left side address ranges contain the street number
potentials = ny_streets.loc[ny_streets["l_low_hn"] street_num]
potentials = potentials.loc[potentials["l_high_hn"] > street_num]
# Find street segments whose zipcode matches the address'
potentials = potentials.loc[potentials["l_zip"] == zipcode]

 

זה מצמצם את הרשימה לקטע רחוב אחד המופיע למטה.

 

XXXXX
 

המשימה האחרונה היא לקבוע היכן נמצאת הכתובת בקו זה. זה נעשה על ידי הצבת מספר הרחוב בתוך טווח הכתובות של הקטע, נורמליזציה כדי לקבוע כמה רחוק לאורך הקו הכתובת צריכה להיות, והחלת קבוע זה על הקואורדינטות של נקודות הקצה של הקו כדי לקבל את הקואורדינטות של הכתובת. הקוד הבא מתאר תהליך זה.

import numpy as np
from shapely.geometry import Point # Calculate how far along the street to place the point
denom = ( potentials["l_high_hn"].astype(float) - potentials["l_low_hn"].astype(float)
).values[0]
normalized_street_num = ( float(street_num) - potentials["l_low_hn"].astype(float).values[0]
) / denom # Define a point that far along the street
# Move the line to start at (0,0)
pizza = np.array(potentials["geometry"].values[0].coords[1]) - np.array( potentials["geometry"].values[0].coords[0]
)
# Multiply by normalized street number to get coordinates on line
pizza = pizza * normalized_street_num
# Add starting segment to place line back on the map
pizza = pizza + np.array(potentials["geometry"].values[0].coords[0])
# Convert to geometry array for geopandas
pizza = gpd.GeoDataFrame( {"address": , "geometry": [Point(pizza[0], pizza[1])]}, crs=ny_streets.crs, geometry="geometry",
)

 

לאחר שסיימנו את הקידוד הגיאוגרפי של הכתובת, ניתן כעת לשרטט את מיקומו של מכון הפיצה הזה על מפה כדי להבין את מיקומו. מכיוון שהקוד לעיל הסתכל על מידע הנוגע לצידו השמאלי של קטע רחוב, המיקום בפועל יהיה מעט משמאל לנקודה המשורטטת בבניין בצד שמאל של הכביש. סוף סוף אתה יודע איפה אתה יכול להשיג פיצה.

 

XXXXX
 

תהליך זה מכסה את מה שמכונה בדרך כלל קידוד גיאוגרפי, אבל זה לא הדרך היחידה שבה משתמשים במונח. ייתכן שתראה גם קידוד גיאוגרפי מתייחס לתהליך של העברת שמות ציוני דרך לקואורדינטות, מיקוד לקואורדינטות או קואורדינטות לוקטורי GIS. ייתכן שאפילו תשמע קידוד גיאוגרפי הפוך (אשר יסוקר בהמשך) המכונה קידוד גיאוגרפי. הגדרה מקלה יותר לקידוד גיאוגרפי המקיפה את אלה תהיה "העברה בין תיאורי שפה משוערים וטבעיים של מיקומים וקואורדינטות גיאוגרפיות." לכן, בכל פעם שאתה צריך לעבור בין שני סוגי הנתונים האלה, שקול קידוד גיאוגרפי כפתרון.

כחלופה לחזרה על תהליך זה בכל פעם שאתה צריך לקוד גיאוגרפי של כתובות, מגוון נקודות קצה של API, כגון Geocoder הלשכה האמריקאית למפקד האוכלוסין ו Google Geocoding API, לספק שירות קידוד גיאוגרפי מדויק בחינם. כמה אפשרויות בתשלום, כגון Esri’s ArcGIS, Geocodio, ו החכם אפילו מציעים דיוק על הגג עבור כתובות נבחרות, מה שאומר שהקואורדינטה המוחזרת נוחתת בדיוק על גג הבניין במקום ברחוב סמוך. הסעיפים הבאים מתארים כיצד להשתמש בשירותים אלה כדי להתאים קידוד גיאוגרפי לצינור הנתונים שלך באמצעות ה-U.S. Census Bureau Geocoder כדוגמה.

על מנת לקבל את הדיוק הגבוה ביותר האפשרי בעת קידוד גיאוגרפי, עליך תמיד להתחיל בכך שהכתובות שלך מעוצבות כך שיתאימו לסטנדרטים של השירות שבחרת. זה ישתנה מעט בין כל שירות, אבל פורמט נפוץ הוא פורמט USPS של "PRIMARY# STREET, CITY, STATE, ZIP" כאשר STATE הוא קוד קיצור, PRIMARY# הוא מספר הרחוב, וכל האזכורים של מספרי סוויטות, בניין מספרים ותיבות דואר מוסרות. 

לאחר עיצוב הכתובת שלך, עליך לשלוח אותה ל-API לצורך קידוד גיאוגרפי. במקרה של ה-U.S. Census Bureau Geocoder, אתה יכול לשלוח את הכתובת באופן ידני דרך הכרטיסייה One Line Address Processing או להשתמש ב- סיפק REST API כדי לשלוח את הכתובת באופן תוכנתי. ה-U.S. Census Bureau Geocoder מאפשר לך גם לקוד גיאוגרפי של קבצים שלמים באמצעות קודן ה-batch ולציין את מקור הנתונים באמצעות פרמטר ה-benchmark. לקידוד גיאוגרפי של הפיצה מקודם, קישור זה ניתן להשתמש כדי להעביר את הכתובת ל- REST API, מה שניתן לעשות ב- Python עם הקוד הבא.

# Submit the address to the U.S. Census Bureau Geocoder REST API for processing
response = requests.get( "https://geocoding.geo.census.gov/geocoder/locations/onelineaddress?address=2709+Broadway%2C+New+York%2C+NY+10025&benchmark=Public_AR_Current&format=json"
).json()

 

הנתונים המוחזרים הם קובץ JSON, שמפוענח בקלות למילון Python. הוא מכיל שדה "tigerLineId" שניתן להשתמש בו כדי להתאים את קובץ הצורה עבור הרחוב הקרוב ביותר, שדה "צד" שבו ניתן להשתמש כדי לקבוע באיזה צד של הרחוב הכתובת נמצאת, ושדות "fromAddress" ו-"toAddress". המכילים את טווח הכתובות עבור קטע הרחוב. והכי חשוב, הוא מכיל שדה "קואורדינטות" שניתן להשתמש בו כדי לאתר את הכתובת על המפה. הקוד הבא מחלץ את הקואורדינטות מקובץ JSON ומעבד אותו ל-GeoDataFrame כדי להכין אותו לניתוח מרחבי.

# Extract coordinates from the JSON file
coords = response["result"]["addressMatches"][0]["coordinates"]
# Convert coordinates to a Shapely Point
coords = Point(coords["x"], coords["y"])
# Extract matched address
matched_address = response["result"]["addressMatches"][0]["matchedAddress"]
# Create a GeoDataFrame containing the results
pizza_point = gpd.GeoDataFrame( {"address": [matched_address], "geometry": coords}, crs=ny_streets.crs, geometry="geometry",
)

 

הדמיה של נקודה זו מראה שהיא נמצאת מעט מחוץ לכביש משמאל לנקודה שקודדה גיאוגרפית באופן ידני.

 

XXXXX

קידוד גיאוגרפי הפוך הוא תהליך של לקיחת קואורדינטות גיאוגרפיות והתאמתן לתיאורי שפה טבעית של אזור גיאוגרפי. כאשר מיישמים אותה בצורה נכונה, זוהי אחת הטכניקות החזקות ביותר לצירוף נתונים חיצוניים בערכת הכלים למדעי הנתונים. השלב הראשון של קידוד גיאוגרפי הפוך הוא קביעת גיאוגרפיות היעד שלך. זה האזור שיכיל את נתוני הקואורדינטות שלך. כמה דוגמאות נפוצות הן רשימות מפקד, מיקודים וערים. השלב השני הוא קביעה באיזה, אם בכלל, מבין אותם אזורים נמצאת הנקודה. בעת שימוש באזורים משותפים, מפקד האוכלוסין האמריקאי ניתן להשתמש כדי להפוך קוד גיאוגרפי על ידי ביצוע שינויים קטנים בבקשת REST API. בקשה לקביעה באילו אזורים גיאוגרפיים של מפקד האוכלוסין יש את מכון הפיצה מלפני כן כאן. ניתן לעבד את התוצאה של שאילתה זו באותן שיטות כמו קודם. עם זאת, הגדרה יצירתית של האזור כך שיתאים לצורך ניתוח והיפוך קידוד גיאוגרפי אליו ידני פותחת אפשרויות רבות. 

כדי להפוך את הקוד הגיאוגרפי באופן ידני, עליך לקבוע את המיקום והצורה של אזור, ולאחר מכן לקבוע אם הנקודה נמצאת בחלק הפנימי של אותו אזור. קביעה אם נקודה נמצאת בתוך מצולע היא למעשה בעיה קשה למדי, אבל אלגוריתם הליהוק קרני, כאשר קרן שמתחילה בנקודה ונעה בכיוון אינסופי חותכת את גבול האזור מספר אי זוגי של פעמים אם היא בתוך האזור ומספר זוגי של פעמים אחרת (שמרת), יכולה לשמש כדי לפתור אותה ברוב מקרים. עבור בעלי נטייה מתמטית, זהו למעשה יישום ישיר של משפט עקומת ירדן (הוש). הערה, אם אתה משתמש בנתונים מרחבי העולם, אלגוריתם הטלת הקרניים יכול למעשה להיכשל מכיוון שקרן תעטוף בסופו של דבר את פני כדור הארץ ותהפוך למעגל. במקרה זה, במקום זאת תצטרך למצוא את המספר המתפתל (Weisstein) עבור האזור והנקודה. הנקודה נמצאת בתוך האזור אם המספר המתפתל אינו אפס. למרבה המזל, ספריית הגיאופנדות של Python מספקת את הפונקציונליות הדרושה גם להגדרת פנים של אזור מצולע וגם לבדוק אם נקודה נמצאת בתוכו ללא כל המתמטיקה המורכבת.

בעוד קידוד גיאוגרפי ידני יכול להיות מורכב מדי עבור יישומים רבים, קידוד גיאוגרפי הפוך ידני יכול להיות תוספת מעשית למערך המיומנויות שלך מכיוון שהוא מאפשר לך להתאים בקלות את הנקודות שלך לאזורים מותאמים במיוחד. לדוגמה, נניח שאתה רוצה לקחת את פרוסת הפיצה שלך לפארק ולעשות פיקניק. אולי תרצו לדעת אם הפיצה נמצאת במרחק קצר מפארק. העיר ניו יורק מספקת קבצי צורה לפארקים שלהם כחלק מה מערך נתונים של נכסי פארקים (NYC Parks Open Data Team), וניתן לגשת אליהם גם דרך ה-SODA API שלהם באמצעות הקוד הבא.

# Pull NYC park shapefiles
parks = gpd.read_file( BytesIO( requests.get( "https://data.cityofnewyork.us/resource/enfh-gkve.geojson?$limit=5000" ).content )
)
# Limit to parks with green area for a picnic
parks = parks.loc[ parks["typecategory"].isin( [ "Garden", "Nature Area", "Community Park", "Neighborhood Park", "Flagship Park", ] )
]

 

ניתן להוסיף פארקים אלו להדמיה כדי לראות אילו פארקים נמצאים בקרבת הפיצה.

 

XXXXX
 

ברור שיש כמה אפשרויות בקרבת מקום, אבל להבין את המרחק באמצעות קבצי הצורה והנקודה יכולה להיות קשה ויקרה מבחינה חישובית. במקום זאת, ניתן להחיל קידוד גיאוגרפי הפוך. השלב הראשון, כאמור לעיל, הוא קביעת האזור אליו ברצונך לצרף את הנקודה. במקרה זה, האזור נמצא "מרחק של 1/2 מייל מפארק בניו יורק." השלב השני הוא חישוב אם הנקודה נמצאת בתוך אזור, שניתן לעשות זאת באופן מתמטי באמצעות השיטות שהוזכרו קודם לכן או על ידי יישום הפונקציה "מכיל" בגיאופנדות. הקוד הבא משמש להוספת חוצץ של 1/2 מייל לגבולות הפארקים לפני בדיקה כדי לראות אילו אזורים מאוגרים של הפארקים מכילים כעת את הנקודה.

# Project the coordinates from latitude and longitude into meters for distance calculations
buffered_parks = parks.to_crs(epsg=2263)
pizza_point = pizza_point.to_crs(epsg=2263)
# Add a buffer to the regions extending the border by 1/2 mile = 2640 feet
buffered_parks = buffered_parks.buffer(2640)
# Find all parks whose buffered region contains the pizza parlor
pizza_parks = parks.loc[buffered_parks.contains(pizza_point["geometry"].values[0])]

 

חיץ זה חושף את הפארקים הסמוכים, המודגשים בכחול בתמונה למטה

 

XXXXX
 

לאחר קידוד גיאוגרפי מוצלח, למדת שיש 8 פארקים בטווח של חצי מייל ממכון הפיצה שבהם אתה יכול לעשות את הפיקניק שלך. תהנה מהנתח הזה.
 

XXXXX
Pizza Slice מאת j4p4n

מקורות

  1. לולר, ג'וש ושייס, פיטר. ESRM 250: מבוא למערכות מידע גיאוגרפיות במשאבי יער. הגדרות של GIS, 12 בפברואר 2009, אוניברסיטת וושינגטון, סיאטל. הרצאה בכיתה. https://courses.washington.edu/gis250/lessons/introduction_gis/definitions.html
  2. CSCL PUB. ניו יורק OpenData. https://data.cityofnewyork.us/City-Government/road/svwp-sbcd
  3. תיעוד גיאקודר של לשכת מפקד האוכלוסין האמריקאית. אוגוסט 2022. https://geocoding.geo.census.gov/geocoder/Geocoding_Services_API.pdf 
  4. Shimrat, M., “Algorithm 112: Position of point relative to polygon” 1962, תקשורת של ה- ACM כרך 5 גיליון 8, אוגוסט 1962. https://dl.acm.org/doi/10.1145/368637.368653 
  5. Hosch, William L.. “Jordan curve theorem”. אנציקלופדיה בריטניקה, 13 באפריל 2018, https://www.britannica.com/science/Jordan-curve-theorem
  6. Weisstein, Eric W. “Contour Winding Number.” From MathWorld–A Wolfram Web Resource. https://mathworld.wolfram.com/ContourWindingNumber.html
  7. צוות נתונים פתוחים של NYC Parks. נכסי פארקים. 14 באפריל, 2023. https://nycopendata.socrata.com/Recreation/Parks-Properties/enfh-gkve
  8. j4p4n, "Pizza Slice." מ OpenClipArt. https://openclipart.org/detail/331718/pizza-slice

 
 
אוון מילר הוא עמית מדעי נתונים ב-Tech Impact, שם הוא משתמש בנתונים כדי לתמוך בעמותות ובסוכנויות ממשלתיות עם משימה של טוב חברתי. בעבר, אוון השתמש בלמידת מכונה כדי להכשיר כלי רכב אוטונומיים באוניברסיטת מרכז מישיגן.
 

בול זמן:

עוד מ KDnuggets