Skip to content

Commit 9b573f1

Browse files
committed
2015-11-16
add by city, state, landarea, waterarea method
1 parent 0a39138 commit 9b573f1

4 files changed

Lines changed: 155 additions & 13 deletions

File tree

long_description.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
Welcome to the uszipcode Documentation
22
====================================================================================================
33

4-
``uszipcode`` is the most powerful and easy to use zipcode information searchengine in Python. Besides geometry data (also boundary info), several useful census data points are also served: `population`, `population density`, `total wage`, `average annual wage`, `house of units`, `land area`, `water area`. The geometry and geocoding data is from google map API on Oct 2015. The geometry data in `this another popular zipcode python package <https://pypi.python.org/pypi/zipcode>`_ is not accurate any more, if you exam it on google map. To know more about the data, `click here <http://www.wbh-doc.com.s3.amazonaws.com/uszipcode/uszipcode/data/__init__.html#module-uszipcode.data>`_.
4+
``uszipcode`` is the most powerful and easy to use zipcode information searchengine in Python. Besides geometry data (also boundary info), several useful census data points are also served: `population`, `population density`, `total wage`, `average annual wage`, `house of units`, `land area`, `water area`. The geometry and geocoding data I am using is from google map API on Oct 2015. To know more about the data, `click here <http://www.wbh-doc.com.s3.amazonaws.com/uszipcode/uszipcode/data/__init__.html#module-uszipcode.data>`_. `Another pupolar zipcode Python extension <https://pypi.python.org/pypi/zipcode>`_ has lat, lng accuracy issue, which doesn't give me reliable results of searching by coordinate and radius.
55

66
**Highlight**:
77

8-
1. `rich methods <http://www.wbh-doc.com.s3.amazonaws.com/uszipcode/index.html#list-of-the-way-you-can-search>`_ are provided for getting zipcode anyway you want.
9-
2. `fuzzy city name and state name <http://www.wbh-doc.com.s3.amazonaws.com/uszipcode/index.html#search-by-city-and-state>`_ allows you to search **WITHOUT using exactly accurate input**. **This is very helpful if you need to build a web app with it**.
8+
1. `Rich methods <http://www.wbh-doc.com.s3.amazonaws.com/uszipcode/index.html#list-of-the-way-you-can-search>`_ are provided for getting zipcode anyway you want.
9+
2. `Fuzzy city name and state name <http://www.wbh-doc.com.s3.amazonaws.com/uszipcode/index.html#search-by-city-and-state>`_ allows you to search **WITHOUT using exactly accurate input**. **This is very helpful if you need to build a web app with it**.
1010
3. You can easily `sort your results <http://www.wbh-doc.com.s3.amazonaws.com/uszipcode/index.html#sortby-descending-and-returns-keyword>`_ by `population`, `area`, `wealthy` and etc...
1111

1212
**Quick links**:

readme.rst

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
Welcome to the uszipcode Documentation
22
====================================================================================================
33

4-
``uszipcode`` is the most powerful and easy to use zipcode information searchengine in Python. Besides geometry data (also boundary info), several useful census data points are also served: `population`, `population density`, `total wage`, `average annual wage`, `house of units`, `land area`, `water area`. The geometry and geocoding data is from google map API on Oct 2015. The geometry data in `this another popular zipcode python package <https://pypi.python.org/pypi/zipcode>`_ is not accurate any more, if you exam it on google map. To know more about the data, `click here <http://www.wbh-doc.com.s3.amazonaws.com/uszipcode/uszipcode/data/__init__.html#module-uszipcode.data>`_.
4+
``uszipcode`` is the most powerful and easy to use zipcode information searchengine in Python. Besides geometry data (also boundary info), several useful census data points are also served: `population`, `population density`, `total wage`, `average annual wage`, `house of units`, `land area`, `water area`. The geometry and geocoding data I am using is from google map API on Oct 2015. To know more about the data, `click here <http://www.wbh-doc.com.s3.amazonaws.com/uszipcode/uszipcode/data/__init__.html#module-uszipcode.data>`_. `Another pupolar zipcode Python extension <https://pypi.python.org/pypi/zipcode>`_ has lat, lng accuracy issue, which doesn't give me reliable results of searching by coordinate and radius.
55

66
**Highlight**:
77

8-
1. `rich methods <search_way_>`_ are provided for getting zipcode anyway you want.
9-
2. `fuzzy city name and state name <by_city_and_state_>`_ allows you to search **WITHOUT using exactly accurate input**. **This is very helpful if you need to build a web app with it**.
10-
3. You can easily `sort your results <keyword_>`_ by `population`, `area`, `wealthy` and etc...
8+
1. `Rich methods <http://www.wbh-doc.com.s3.amazonaws.com/uszipcode/index.html#list-of-the-way-you-can-search>`_ are provided for getting zipcode anyway you want.
9+
2. `Fuzzy city name and state name <http://www.wbh-doc.com.s3.amazonaws.com/uszipcode/index.html#search-by-city-and-state>`_ allows you to search **WITHOUT using exactly accurate input**. **This is very helpful if you need to build a web app with it**.
10+
3. You can easily `sort your results <http://www.wbh-doc.com.s3.amazonaws.com/uszipcode/index.html#sortby-descending-and-returns-keyword>`_ by `population`, `area`, `wealthy` and etc...
1111

1212
**Quick links**:
1313

@@ -143,7 +143,7 @@ You can add ``standard_only=False`` parameter to enable returning Po Box type zi
143143
Search by Latitude and Longitude
144144
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
145145

146-
You can search all zipcode with-in range of XXX miles to a coordinate. You can add ``returns=xxx`` to set maxiumum number of zipcode can be returned. By default, it's 5. Use ``returns=0`` to remove the limit. **The results are sorted by the distance from the center, from lowest to highest.
146+
You can search all zipcode with-in range of XXX miles to a coordinate. You can add ``returns=xxx`` to set maxiumum number of zipcode can be returned. By default, it's 5. Use ``returns=0`` to remove the limit. **The results are sorted by the distance from the center, from lowest to highest**.
147147

148148
.. code-block:: python
149149

uszipcode/searchengine.py

Lines changed: 123 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ def by_city_and_state(self, city, state, standard_only=True):
214214
"""Search zipcode information by City and State name.
215215
216216
You can use either short state name and long state name. My engine use
217-
fuzzy search and guess what is you want.
217+
fuzzy match and guess what is you want.
218218
219219
:param city: city name.
220220
:param state: 2 letter short name or long name.
@@ -258,6 +258,76 @@ def by_city_and_state(self, city, state, standard_only=True):
258258
res.append(Zipcode(self.all_column, list(row)))
259259

260260
return res
261+
262+
def by_city(self, city, standard_only=True):
263+
"""Search zipcode information by City and State name.
264+
265+
My engine use fuzzy match and guess what is you want.
266+
267+
:param city: city name.
268+
:param standard_only: boolean, default True, only returns standard
269+
type zipcode
270+
"""
271+
# find out what is the city that user looking for
272+
select_sql = "SELECT City FROM zipcode WHERE City == '%s'" % city
273+
all_city = [record[0] for record in self.cursor.execute(select_sql)]
274+
275+
choice, confidence = extractOne(city.lower(), all_city)
276+
if confidence < 70:
277+
raise Exception("Cannot found '%s' in '%s'." % (city, state))
278+
else:
279+
city = choice
280+
281+
# execute query
282+
select_sql = \
283+
"""
284+
SELECT * FROM zipcode
285+
WHERE City = '%s'
286+
""" % (city,)
287+
if standard_only:
288+
select_sql = select_sql + self._standard_only_param
289+
290+
res = list()
291+
for row in self.cursor.execute(select_sql):
292+
res.append(Zipcode(self.all_column, list(row)))
293+
294+
return res
295+
296+
def by_state(self, state, standard_only=True):
297+
"""Search zipcode information by State name.
298+
299+
You can use either short state name and long state name. My engine use
300+
fuzzy match and guess what is you want.
301+
302+
:param state: 2 letter short name or long name.
303+
:param standard_only: boolean, default True, only returns standard
304+
type zipcode
305+
"""
306+
# check if it is a abbreviate name
307+
if state.upper() in self.all_state_short:
308+
state = state.upper()
309+
# if not, find out what is the state that user looking for
310+
else:
311+
choice, confidence = extractOne(state.lower(), self.all_state_long)
312+
if confidence < 70:
313+
raise Exception("'%s' is not a valid statename, use 2 letter "
314+
"short name or correct full name please." % state)
315+
state = STATE_ABBR_LONG_TO_SHORT[choice]
316+
317+
# execute query
318+
select_sql = \
319+
"""
320+
SELECT * FROM zipcode
321+
WHERE State = '%s'
322+
""" % (state,)
323+
if standard_only:
324+
select_sql = select_sql + self._standard_only_param
325+
326+
res = list()
327+
for row in self.cursor.execute(select_sql):
328+
res.append(Zipcode(self.all_column, list(row)))
329+
330+
return res
261331

262332
def by_prefix(self, prefix, standard_only=True,
263333
sortby="ZipCode", descending=False, returns=_DEFAULT_LIMIT):
@@ -374,6 +444,58 @@ def by_density(self, lower=-1, upper=2**30, standard_only=True,
374444
res.append(Zipcode(self.all_column, list(row)))
375445
return res
376446

447+
def by_landarea(self, lower=-1, upper=2**30, standard_only=True,
448+
sortby="ZipCode", descending=False, returns=_DEFAULT_LIMIT):
449+
"""Search zipcode information by landarea range.
450+
451+
:param lower: minimal landarea
452+
:param upper: maximum landarea
453+
:param standard_only: boolean, default True, only returns standard
454+
type zipcode
455+
:param sortby: string, default ``"Zipcode"``
456+
:param descending: boolean, default False
457+
:param returns: int, default 5
458+
"""
459+
select_sql = \
460+
"""
461+
SELECT * FROM zipcode WHERE LandArea >= %f AND LandArea <= %f
462+
""" % (lower, upper)
463+
if standard_only:
464+
select_sql = select_sql + self._standard_only_param
465+
select_sql = select_sql + self.get_sortby_sql(sortby, descending)
466+
select_sql = select_sql + self.get_limit_sql(returns)
467+
468+
res = list()
469+
for row in self.cursor.execute(select_sql):
470+
res.append(Zipcode(self.all_column, list(row)))
471+
return res
472+
473+
def by_waterarea(self, lower=-1, upper=2**30, standard_only=True,
474+
sortby="ZipCode", descending=False, returns=_DEFAULT_LIMIT):
475+
"""Search zipcode information by landarea range.
476+
477+
:param lower: minimal waterarea
478+
:param upper: maximum waterarea
479+
:param standard_only: boolean, default True, only returns standard
480+
type zipcode
481+
:param sortby: string, default ``"Zipcode"``
482+
:param descending: boolean, default False
483+
:param returns: int, default 5
484+
"""
485+
select_sql = \
486+
"""
487+
SELECT * FROM zipcode WHERE WaterArea >= %f AND WaterArea <= %f
488+
""" % (lower, upper)
489+
if standard_only:
490+
select_sql = select_sql + self._standard_only_param
491+
select_sql = select_sql + self.get_sortby_sql(sortby, descending)
492+
select_sql = select_sql + self.get_limit_sql(returns)
493+
494+
res = list()
495+
for row in self.cursor.execute(select_sql):
496+
res.append(Zipcode(self.all_column, list(row)))
497+
return res
498+
377499
def by_totalwages(self, lower=-1, upper=2**30, standard_only=True,
378500
sortby="ZipCode", descending=False, returns=_DEFAULT_LIMIT):
379501
"""Search zipcode information by total annual wages.

uszipcode/tests/test_searchengine.py

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,21 +31,41 @@ def test_all(self):
3131
self.assertEqual(zipcode.City, "Nickerson")
3232
self.assertEqual(zipcode.State, "KS")
3333

34+
res = search.by_state("RI")
35+
zipcode = res[0]
36+
self.assertEqual(zipcode.Zipcode, "02804")
37+
self.assertEqual(zipcode.City, "Ashaway")
38+
self.assertEqual(zipcode.State, "RI")
39+
40+
res = search.by_city("Vienna")
41+
zipcode = res[0]
42+
self.assertEqual(zipcode.Zipcode, "04360")
43+
self.assertEqual(zipcode.City, "Vienna")
44+
self.assertEqual(zipcode.State, "ME")
45+
3446
res = search.by_prefix("208",
35-
sortby="Population", descending=True, returns=0)
47+
sortby="Zipcode", descending=True, returns=0)
3648
self.assertEqual(len(res), 34)
3749

3850
res = search.by_pattern("100",
39-
sortby="Population", descending=True, returns=0)
51+
sortby="Zipcode", descending=True, returns=0)
4052
self.assertEqual(len(res), 97)
4153

4254
res = search.by_population(lower=100000,
43-
sortby="Population", descending=True, returns=0)
55+
sortby="Population", descending=False, returns=0)
4456
self.assertEqual(len(res), 10)
4557

4658
res = search.by_density(lower=10000,
47-
sortby="Population", descending=True, returns=0)
59+
sortby="Density", descending=False, returns=0)
4860
self.assertEqual(len(res), 631)
61+
62+
res = search.by_landarea(lower=1000,
63+
sortby="LandArea", descending=False, returns=0)
64+
self.assertEqual(len(res), 181)
65+
66+
res = search.by_waterarea(lower=100,
67+
sortby="WaterArea", descending=False, returns=0)
68+
self.assertEqual(len(res), 30)
4969

5070
res = search.by_totalwages(lower=1000**3,
5171
sortby="Population", descending=True, returns=0)

0 commit comments

Comments
 (0)