Trying to use the latitude and longitude that is returned by geopy to create a shapefile. The shapefile creator part works line if I give it a set of numbers (44.977753, -93.2650108) but it will not work with the returned data lat_long. My thought is that it needs a "," but I dont know.
from geopy.geocoders import GoogleV3
import csv
import ogr, os
def geopy():
loc = raw_input("What location? ")
geolocator = GoogleV3()
location = geolocator.geocode(loc, exactly_one=True)
if location != None:
Address = location.address
lat_long = location.latitude, location.longitude
latitude = str(location.latitude)
longitude = str(location.longitude)
print Address, latitude, longitude
print""
else:
print "There is no geographic information to return for the word in input. \n"
# Input data
pointCoord = lat_long
fieldName = 'test'
fieldType = ogr.OFTString
fieldValue = 'test'
outSHPfn = "output file"
# create the spatial reference, WGS84
srs = osr.SpatialReference()
srs.ImportFromEPSG(4326)
# Create the output shapefile
shpDriver = ogr.GetDriverByName("ESRI Shapefile")
if os.path.exists(outSHPfn):
shpDriver.DeleteDataSource(outSHPfn)
outDataSource = shpDriver.CreateDataSource(outSHPfn)
outLayer = outDataSource.CreateLayer(outSHPfn, srs, geom_type = ogr.wkbPoint )
#create point geometry
point = ogr.Geometry(ogr.wkbPoint)
point.AddPoint(pointCoord[0],pointCoord[1])
# create a field
idField = ogr.FieldDefn(fieldName, fieldType)
outLayer.CreateField(idField)
# Create the feature and set values
featureDefn = outLayer.GetLayerDefn()
outFeature = ogr.Feature(featureDefn)
outFeature.SetGeometry(point)
outFeature.SetField(fieldName, fieldValue)
outLayer.CreateFeature(outFeature)
geopy()
Need to add a loop to put the latitude and longitude in a list. This code will create a point shapefile of any location you give it.
from geopy.geocoders import GoogleV3
import csv
import ogr, os
def geopy(location):
"""This function takes the word given about
and uses GoogleV3 to search for a location. If a
location is found it then returns the Address, latitude and longitude.
It then prints that information to a .CSV"""
geolocator = GoogleV3()
loc_input = raw_input("Add the location you would like data back for: ")
location = geolocator.geocode(loc_input, exactly_one=True)
if location != None:
Address = location.address
lat_lon = location.latitude, location.longitude
latitude = str(location.latitude)
longitude = str(location.longitude)
print Address, latitude, longitude
print""
#Converts lat_long to a list for use in making the shapefile.
list_lat = []
for i in range(1):
list_lat.append(lat_lon)
for list_of_lat_lon in list_lat:
print""
#Calls list_of_lat_lon for the shapefile function
shapefile(list_of_lat_lon)
# If there is no location data to return it prints the below line and does not create a shapefile
else:
print "There is no geographic information to return for the word in input. \n"
def shapefile(list_of_lat_lon):
"""This function uses the GDAL to return a ESRi shapefile
it uses the latitude and longitude in the list_of_lat_lon list.
"""
# Input data
pointCoord = list_of_lat_lon
fieldName = 'Lat'
fieldType = ogr.OFTString
fieldValue = 'test'
outSHPfn = "Input file location"
# create the spatial reference, WGS84
srs = osr.SpatialReference()
srs.ImportFromEPSG(4326)
# Create the output shapefile
shpDriver = ogr.GetDriverByName("ESRI Shapefile")
if os.path.exists(outSHPfn):
shpDriver.DeleteDataSource(outSHPfn)
outDataSource = shpDriver.CreateDataSource(outSHPfn)
outLayer = outDataSource.CreateLayer(outSHPfn, srs, geom_type = ogr.wkbPoint )
#create point geometry longitude first then latitude
point = ogr.Geometry(ogr.wkbPoint)
point.AddPoint(pointCoord[1],pointCoord[0])
# create a field
idField = ogr.FieldDefn(fieldName, fieldType)
outLayer.CreateField(idField)
# Create the feature and set values
featureDefn = outLayer.GetLayerDefn()
outFeature = ogr.Feature(featureDefn)
outFeature.SetGeometry(point)
outFeature.SetField(fieldName, fieldValue)
outLayer.CreateFeature(outFeature)
geopy(location)
Related
from geopy.geocoders import Nominatim
geolocator = Nominatim(user_agent="My App")
#tries fetch address from geopy
location = geolocator.geocode(df2['address'])
#append lat/long to column using dataframe location
df2.loc['lat'] = location.latitude
df2.loc['long'] = location.longitude
#catches exception for the case where no value is returned
#appends null value to column
df2.loc['lat'] = ""
df2.loc['long'] = ""
df2.head()
Here is the code that I tried using ^^^
geolocator = Nominatim(user_agent="My App")
location = geolocator.geocode("33000 N KINGSHIGHWAY BLVD, St.Louis" )
print((location.latitude, location.longitude))
This Code above worked when I picked only one address. But ofc I want it to run without me giving it a specific address.
def get_lat_long(address):
try:
x = geolocator.geocode(address)
return x.latitude, x.longitude
except:
return np.nan, np.nan
df[['latitude', 'longitude']] = df.apply(lambda x: get_lat_long(x.address), axis=1, result_type='expand')
print(df)
Output:
address latitude longitude
0 33000 N KINGSHIGHWAY BLVD, St.Louis 38.649933 -90.263803
This is untested, because I don't want to install the package, but this is the kind of thing you need:
from geopy.geocoders import Nominatim
geolocator = Nominatim(user_agent="My App")
lat, lon = [], []
for addr in df2['address'].tolist():
location = geolocator.geocode(addr)
lat.append( location.latitude )
lon.append( location.longitude )
df2['latitude'] = np.array(lat)
df2['longitude'] = np.array(lon)
Or:
locs = [geolocator.geocode(addr) for addr in df2['address'].tolist()]
locs = np.array(locs)
df2['latitide'] = locs[:,0]
df2['longitude'] = locs[:,1]
I am trying to get the co-ordinates and distance but getting inconsistencies from Bing Maps API. Is there something I'm doing wrong or do the responses really vary that much?
Issue: The co-ordinates that I get in the JSON response are different for the same starting address.
My input is an excel file with the starting and delivery addresses like so
df = df[['Starting Address', 'Delivery Address', 'Driving Distance (Miles)', 'Radial Distance (Miles)']]
df = df.reset_index()
for index, row in df.iterrows():
#Encoding Addresses
enc_start = urllib.parse.quote(df['Starting Address'][index], safe='')
print(enc_start)
enc_del = urllib.parse.quote(df['Delivery Address'][index], safe='')
print(enc_del)
#API Call
url = "http://dev.virtualearth.net/REST/V1/Routes/Driving?wp.0=" + enc_start + "&wp.1=" + enc_del + "&distanceUnit=mi" + "&optmz=distance" + "&key=" + bingMapsKey
response = requests.get(url).json() #Setting API response (JSON)
try:
s_lat = response["resourceSets"][0]["resources"][0]["bbox"][2] #Fetching Starting Address Latitude
s_lon = response["resourceSets"][0]["resources"][0]["bbox"][3] #Fetching Starting Address Longitude
d_lat = response["resourceSets"][0]["resources"][0]["bbox"][0] #Fetching Delivery Address Latitude
d_lon = response["resourceSets"][0]["resources"][0]["bbox"][1] #Fetching Delivery Address Longitude
coords_start = (s_lat, s_lon) #Coords of Starting Address
coords_del = (d_lat, d_lon) #Coords of Delivery Address
print("c_str ", coords_start)
print("c_del ", coords_del)
#Optimized Travel Distance
travelDistance = response["resourceSets"][0]["resources"][0]["travelDistance"]
print("travel dist ", travelDistance)
df.loc[[index], 'Driving Distance (Miles)'] = travelDistance
# folium.Marker(location=[d_lat, d_lon], popup = df["Delivery Address"][index]).add_to(mc) #Creating Output Map
except:
IndexError
#Radial Distance
radialDistance = haversine(coords_start, coords_del, unit=Unit.MILES)
# # print(radialDistance)
df.loc[[index], 'Radial Distance (Miles)'] = radialDistance
Output:
You are grabbing the bounding box coordinates rather than at actual starting location. The bounding box is just a recommendation for viewing the full route and would change if both the start and end are not identical between queries.
To get the actual start/end points;
s_lat = response["resourceSets"][0]["resources"][0]["routeLegs"][0]["actualStart"]["coordinates"][0]
s_lon = response["resourceSets"][0]["resources"][0]["routeLegs"][0]["actualStart"]["coordinates"][1]
d_lat = response["resourceSets"][0]["resources"][0]["routeLegs"][0]["actualEnd"]["coordinates"][0]
d_lon = response["resourceSets"][0]["resources"][0]["routeLegs"][0]["actualEnd"]["coordinates"][1]
I have a netcdf file with global wind data and I need to extract the component of wind UGRD& VGRD for my study area (lonmin=-2, lonmax=8, latmin=35 latmax=39). I need to have a text file with this format:
time series UGRD
VGRD
Example
19790101060000 (year month day hours)
3.28 5.26 (UGRD)
2.23 2.225 (VGRD)
I tried to do this operation with python. I succeeded to extract my study area in nc file but, I still tried to convert it to a text file but I've failed. Can someone help me to do it, please?
import numpy as np
import netCDF4
import netCDF4 as nc
import pandas as pd
import numpy as np
import csv
#### === User-inputs ====#####
one = nc.Dataset('1979.nc') ##load one of your nc datafiles
print one.variables ## Check variables names, say my variable names are lat, lon, pre
## Name of the variables
lat_name = 'latitude'
lon_name = 'longitude'
time_name = 'time'
data_name1 = 'UGRD_10maboveground'
data_name2 = 'VGRD_10maboveground'
## Select spatial range for which data to be extracted
mylat1 = 35
mylat2 = 39
mylon1 = -2
mylon2 = 8
##Give a name of your extracted datafile and define units
newfilename = 'Extracted_Data'
time_unit = 'day since 1979-01-01 00:00'
lat_unit = 'degrees_south'
lon_unit = 'degrees_east'
data_unit = 'm/s'
#### ======= Rest of the Code is Automated ========######
##Find pixel-range based on the provided lat-lon
lat = one.variables[lat_name][:]
lon = one.variables[lon_name][:]
ver_pix = []
for i in xrange(0, len(lat)):
if lat[i] >= mylat1 and lat[i] <= mylat2:
ver_pix.append(i)
y_min = min(ver_pix)
y_max = max(ver_pix)
print lat[min(ver_pix):max(ver_pix)]
hor_pix = []
for j in xrange(0,len(lon)):
if lon[j] >= mylon1 and lon[j] <= mylon2:
hor_pix.append(j)
x_min = min(hor_pix)
x_max = max(hor_pix)
print lon[min(hor_pix):max(hor_pix)]
check_range1 = one.variables[data_name1][:,y_min:y_max,x_min:x_max] ##pre:lat:lon =
time,y,x
check_range2 = one.variables[data_name2][:,y_min:y_max,x_min:x_max]
#print check_range
print check_range1.shape
print check_range2.shape
## Load all nc files in the directory from which data to be extracted
## ..for the selected area
f = nc.MFDataset('1979.nc')
alldata = f.variables[data_name1][:,y_min:y_max,x_min:x_max]
alldata = f.variables[data_name2][:,y_min:y_max,x_min:x_max]
lat1 = one.variables[lat_name][y_min:y_max]
lon1 = one.variables[lon_name][x_min:x_max]
#time = one.variables[time_name][:]
ncfile = nc.Dataset(''+str(newfilename)+'.nc','w')
ncfile.createDimension(time_name,len(alldata))
ncfile.createDimension(lat_name,len(lat1))
ncfile.createDimension(lon_name,len(lon1))
time = ncfile.createVariable(time_name,np.dtype('float32').char,(time_name,))
lats = ncfile.createVariable(lat_name,np.dtype('float32').char,(lat_name,))
lons = ncfile.createVariable(lon_name,np.dtype('float32').char,(lon_name,))
time.units = time_unit
lats.units = lat_unit
lons.units = lon_unit
time[:] = np.linspace(1,len(alldata),len(alldata))
lats[:] = lat1
lons[:] = lon1
newdata1 = ncfile.createVariable(data_name1,np.dtype('float32').char,
(time_name,lat_name,lon_name))
newdata2 = ncfile.createVariable(data_name2,np.dtype('float32').char,
(time_name,lat_name,lon_name))
newdata1.units = data_unit
newdata2.units = data_unit
newdata1[:] = alldata[:]
newdata2[:] = alldata[:]
dtime=netCDF4.num2date(time[:],time.units)
UGRD_ts=pd.Series(data_name2,index=dtime)
UGRD_ts.to_csv('data1.csv', index=True, header=True)
The purpose of the code is to make a PDF map book that displays all of the large lakes in North America. I'm trying to run this code to make a map book but it gives me a blank PDF. How can I fix this?
## Import arcpy module
import arcpy
import math
import os
from arcpy import env
arcpy.env.overwriteOutput = True
# Define inputs and outputs - Script arguments
arcpy.env.workspace = r"F:\Geog173\Lab7\Lab7_Data"
Lakes = "NA_Big_Lakes.shp"
Cities = "NA_Cities.shp"
NA = "North_America.shp"
##Python arguments
## Arguments = NA_Big_Lakes.shp NA_Cities.shp New_Lakes.shp Center_Lakes.shp
Lakes= 'NA_Big_Lakes.shp'
NA = 'North_America.shp'
Cities = 'NA_Cities.shp'
##New_Lakes = 'New_Lakes.shp'
##Center_Lakes = 'Center_Lakes.shp'
# Identify the geometry field
desc = arcpy.Describe(Lakes)
shapeName = desc.ShapeFieldName
# Identify the geometry field in Cities shapefile
##desc = arcpy.Describe(Cities)
##shapefieldnameCity = desc.ShapeFieldName
#Get lake cursor
inrows = arcpy.SearchCursor(Lakes)
# Set up variables for output path and PDF file name
outDir = r"F:\Geog173\Lab7\Lab7_Data"
finalMapPDF_filename = outDir + r"\NA_Big_Lake_Mapbook.pdf"
# Check whether the mapbook PDF exists. If it does, delete it.
if os.path.exists(finalMapPDF_filename):
os.remove(finalMapPDF_filename)
# Create map book PDF
finalMapPDF = arcpy.mapping.PDFDocumentCreate(finalMapPDF_filename)
# Create MapDocument object pointing to specified mxd
mxd = arcpy.mapping.MapDocument(outDir + r"\OriginalMap.mxd")
# Get dataframe
df = arcpy.mapping.ListDataFrames(mxd)[0]
# ----------------------------------------------------------------------------#
# Start appending pages. Title page first.
# ----------------------------------------------------------------------------#
# Find text element with value "test", and replace it with other value
mapText = "A Map Book for North American Large Lakes " + '\n\r' + "Kishore, A., Geog173, Geography, UCLA" + '\n\r' + " Lake number: 18" + '\n\r' + " Total area: 362117 km2" + '\n\r' + " Mean area: 20118 km2"
print mapText
for elm in arcpy.mapping.ListLayoutElements(mxd, "TEXT_ELEMENT"):
if elm.text == "test":
elm.text = mapText
arcpy.RefreshTOC()
arcpy.RefreshActiveView()
#df.extent = feature.extent
arcpy.mapping.ExportToPDF(mxd, outDir + r"\TempMapPages.pdf")
# Append multi-page PDF to finalMapPDF
finalMapPDF.appendPages(outDir + r"\TempMapPages.pdf")
#initialize text value, so it can be reused in next iteration
for elm in arcpy.mapping.ListLayoutElements(mxd, "TEXT_ELEMENT"):
if elm.text == mapText:
elm.text = "test"
# ----------------------------------------------------------------------------#
# Loop through each lake
# ----------------------------------------------------------------------------#
# Loop through each row/feature
lakecount = 0
for row in inrows:
lakecount = lakecount + 1
CITY_NAME = ""
CNTRY_NAME = ""
ADMIN_NAME = ""
POP_CLASS = ""
DISTANCE = 0
XY = ""
#print "shapeName" , shapeName
# Create the geometry object
feature = row.getValue(shapeName)
mapText = "Lake FID: " + str(row.FID) + ", Area (km2): " + str(row.Area_km2)
print mapText
# Find text element with value "test", and replace it with other value
for elm in arcpy.mapping.ListLayoutElements(mxd, "TEXT_ELEMENT"):
if elm.text == "test":
elm.text = mapText
arcpy.RefreshTOC()
arcpy.RefreshActiveView()
df.extent = feature.extent
arcpy.mapping.ExportToPDF(mxd, outDir + r"\TempMapPages.pdf")
# Append multi-page PDF to finalMapPDF
finalMapPDF.appendPages(outDir + r"\TempMapPages.pdf")
# Set up properties for Adobe Reader and save PDF.
finalMapPDF.updateDocProperties(pdf_open_view = "USE_THUMBS",
pdf_layout = "SINGLE_PAGE")
finalMapPDF.saveAndClose()
# Done. Clean up and let user know the process has finished.
del row, inrows
del mxd, finalMapPDF
print "Map book for lakes in North America is complete!"
First off you should remove the last lines of your code where you delete the mxd. Run the code again and inspect the MXD. Are the data layers drawing properly? I recommend having code that completely works before performing file cleanup so you can identify potential errors.
I am using OGR Distance in Python to determine the shortest distance between a point and a line. My results are completely different then the ones I get using QGIS. I assume the units OGR uses depend on the coordinate system? Could it be that OGR uses degrees? If so how could I convert these to meters?
My code looks like this:
import ogr
driver = ogr.GetDriverByName('ESRI Shapefile')
roads = driver.Open('G:/Basedata/OR/infra/TigerRoads2010/OR_TIGERroads_2010_merge.shp', 0)
point = driver.Open('U:/My Documents/Tool/shp/testareacentro.shp', 0)
roadslayer = roads.GetLayer()
pointl = point.GetLayer()
roadsfeature = roadslayer.GetNextFeature()
pointf = pointl.GetNextFeature()
roadgeom = roadsfeature.GetGeometryRef()
pointgeom = pointf.GetGeometryRef()
dist = pointgeom.Distance(roadgeom)
print dist
The reason why my distance is off, is because I only compared the first feature.
This will code will give the same results as in QGIS:
import ogr
driver = ogr.GetDriverByName('ESRI Shapefile')
lineshp = driver.Open('U:/My Documents/Tool/shp/line.shp', 0)
linelyr = lineshp.GetLayer()
pointshp = driver.Open('U:/My Documents/Tool/shp/point.shp', 0)
pointlyr = pointshp.GetLayer()
linefeat = linelyr.GetNextFeature()
pointfeat = pointlyr.GetNextFeature()
point_geom = pointfeat.GetGeometryRef()
distlist = []
while linefeat:
line_geom = linefeat.GetGeometryRef()
dist = point_geom.Distance(line_geom)
distlist.append(dist)
linefeat.Destroy()
linefeat = linelyr.GetNextFeature()
print min(distlist)