I have a simple Python script that queries an API and parses the JSON data. Specifically, I am trying to find all id
s that fall into a rectangle based on given latitude and longitude coordinates. I am having some data type issues since one is being returned as type str
and the other as type float
. The coordinates are: (37.769754, -122.427050)
and, (37.748554, -122.404535)
.
Below is my code, sample JSON, and the trace.
Code:
import requests
def get_ids():
url = "https://retro.umoiq.com/service/publicJSONFeed?command=vehicleLocations&a=sf-muni&t=0"
response = requests.get(url).json()
id_list = []
for i in response['vehicle']:
lat = i['lat']
lon = i['lon']
if (lat < 37.769754 and lon < -122.427050):
if (lat < 37.748554 and lon < -122.404535):
id_list.append(i['id'])
print(id_list)
def main():
get_ids()
if __name__ == "__main__":
main()
JSON:
{'lastTime': {'time': '1653259435728'}, 'copyright': 'All data copyright San Francisco Muni 2022.', 'vehicle': [{'routeTag': 'KT', 'predictable': 'true', 'heading': '218', 'speedKmHr': '0', 'lon': '-122.405464', 'id': '1462', 'dirTag': 'KT___O_F20', 'lat': '37.708099', 'secsSinceReport': '33', 'leadingVehicleId': '1487'}, {'routeTag': '33', 'predictable': 'true', 'heading': '165', 'speedKmHr': '35', 'lon': '-122.40744', 'id': '5817', 'dirTag': '33___O_F00', 'lat': '37.763451', 'secsSinceReport': '6'}, {'routeTag': '1', 'predictable': 'true', 'heading': '269', 'speedKmHr': '0', 'lon': '-122.492844', 'id': '5818', 'dirTag': '1____O_F00', 'lat': '37.77985', 'secsSinceReport': '33'}, {'routeTag': '1', 'predictable': 'true', 'heading': '219', 'speedKmHr': '0', 'lon': '-122.493156', 'id': '5819', 'lat': '37.779823', 'secsSinceReport': '6'}, {'routeTag': 'N', 'predictable': 'true', 'heading': '195', 'speedKmHr': '6', 'lon': '-122.457748', 'id': '1453', 'dirTag': 'N____O_F01', 'lat': '37.764671', 'secsSinceReport': '33'}, {'routeTag': '24', 'predictable': 'true', 'heading': '231', 'speedKmHr': '0', 'lon': '-122.412033', 'id': '5813', 'dirTag': '24___I_F00', 'lat': '37.739773', 'secsSinceReport': '20'}, {'routeTag': '1', 'predictable': 'true', 'heading': '80', 'speedKmHr': '0', 'lon': '-122.397522', 'id': '5815', 'dirTag': '1____I_F00', 'lat': '37.795418', 'secsSinceReport': '46'}, {'routeTag': '1', 'predictable': 'true', 'heading': '87', 'speedKmHr': '0', 'lon': '-122.472931', 'id': '5827', 'dirTag': '1____I_F00', 'lat': '37.78437', 'secsSinceReport': '6'}, {'routeTag': 'KT', 'predictable': 'true', 'heading': '330', 'speedKmHr': '32', 'lon': '-122.468117', 'id': '1469', 'dirTag': 'KT___I_F20', 'lat': '37.7290149', 'secsSinceReport': '6'}, {'routeTag': '33', 'predictable': 'true', 'heading': '77', 'speedKmHr': '0', 'lon': '-122.456421', 'id': '5828', 'dirTag': '33___O_F00', 'lat': '37.786957', 'secsSinceReport': '6'}, {'routeTag': '45', 'predictable': 'true', 'heading': '165', 'speedKmHr': '21', 'lon': '-122.406647', 'id': '5829', 'dirTag': '45___I_F00', 'lat': '37.78756', 'secsSinceReport': '6'}
etc...
Trace:
Traceback (most recent call last):
File "/main.py", line 51, in <module>
main()
File "/main.py", line 48, in main
get_ids()
File "/main.py", line 41, in get_ids
if (lat < 37.769754 and lon < -122.427050):
TypeError: '<' not supported between instances of 'str' and 'float'
CodePudding user response:
Try converting the data to floats like so:
lat = float(i['lat'])
lon = float(i['lon'])
This will allow the comparison operators to work correctly when comparing 2 floats.
Keep in mind the operators themselves are wrong (long -179
and lat -179
would fit inside your rectangle).
I took the liberty to improve some of your code and fix the comparison operators:
import requests
VEHICLE_LOCATIONS_URL = "https://retro.umoiq.com/service/publicJSONFeed?command=vehicleLocations&a=sf-muni&t=0"
# (min_lat, max_lat), (min_long, max_long)
BOUNDARIES = ((37.748554, 37.769754), (-122.427050, -122.404535))
def get_ids_in_boundry():
response = requests.get(VEHICLE_LOCATIONS_URL).json()
id_list = []
for vehicle in response['vehicle']:
lat, long = float(vehicle['lat']), float(vehicle['lon'])
if ((BOUNDARIES[0][0] <= lat <= BOUNDARIES[0][1])
and (BOUNDARIES[1][0] <= long <= BOUNDARIES[1][1])):
id_list.append(vehicle['id'])
return id_list
def main():
print(get_ids_in_boundry())
if __name__ == "__main__":
main()
I've changed the URL to be a const, so as the boundaries, and returned the id_list
outside of the function. Many other improvements can be added such as asking for boundaries in the function parameter or splitting doing the request and checking the boundaries into 2 different functions.
CodePudding user response:
If I understood everything correctly the aswer is to convert the variables lat
and lon
to floats.
To do that just modify this in your code
lat = float(i['lat'])
lon = float(i['lon'])