Skip to content

Commit 3156d71

Browse files
authored
Merge pull request #449 from bashtage/kurtforrester-base-freq
Kurtforrester base freq
2 parents 8d3e50f + c88c906 commit 3156d71

File tree

3 files changed

+106
-17
lines changed

3 files changed

+106
-17
lines changed

pandas_datareader/base.py

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,25 +19,29 @@ class _BaseReader(object):
1919
"""
2020
Parameters
2121
----------
22-
sym : string with a single Single stock symbol (ticker).
22+
symbols : {str, List[str]}
23+
String symbol of like of symbols
2324
start : string, (defaults to '1/1/2010')
24-
Starting date, timestamp. Parses many different kind of date
25-
representations (e.g., 'JAN-01-2010', '1/1/10', 'Jan, 1, 1980')
25+
Starting date, timestamp. Parses many different kind of date
26+
representations (e.g., 'JAN-01-2010', '1/1/10', 'Jan, 1, 1980')
2627
end : string, (defaults to today)
27-
Ending date, timestamp. Same format as starting date.
28+
Ending date, timestamp. Same format as starting date.
2829
retry_count : int, default 3
29-
Number of times to retry query request.
30+
Number of times to retry query request.
3031
pause : float, default 0.1
31-
Time, in seconds, of the pause between retries.
32+
Time, in seconds, of the pause between retries.
3233
session : Session, default None
33-
requests.sessions.Session instance to be used
34+
requests.sessions.Session instance to be used
35+
freq : {str, None}
36+
Frequency to use in select readers
3437
"""
3538

3639
_chunk_size = 1024 * 1024
3740
_format = 'string'
3841

39-
def __init__(self, symbols, start=None, end=None,
40-
retry_count=3, pause=0.1, timeout=30, session=None):
42+
def __init__(self, symbols, start=None, end=None, retry_count=3,
43+
pause=0.1, timeout=30, session=None, freq=None):
44+
4145
self.symbols = symbols
4246

4347
start, end = _sanitize_dates(start, end)
@@ -51,6 +55,7 @@ def __init__(self, symbols, start=None, end=None,
5155
self.timeout = timeout
5256
self.pause_multiplier = 1
5357
self.session = _init_session(session, retry_count)
58+
self.freq = freq
5459

5560
def close(self):
5661
""" close my session """

pandas_datareader/tests/test_wb.py

Lines changed: 64 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
import time
2-
import pytest
32

43
import numpy as np
54
import pandas as pd
5+
import pandas.util.testing as tm
6+
import pytest
67
import requests
78

8-
import pandas.util.testing as tm
9+
from pandas_datareader.compat import assert_raises_regex
910
from pandas_datareader.wb import (search, download, get_countries,
1011
get_indicators, WorldBankReader)
11-
from pandas_datareader.compat import assert_raises_regex
1212

1313

1414
class TestWB(object):
@@ -214,3 +214,64 @@ def test_wdi_get_indicators(self):
214214
# assert_index_equal doesn't exists
215215
assert result.columns.equals(exp_col)
216216
assert len(result) > 10000
217+
218+
def test_wdi_download_monthly(self):
219+
expected = {'COPPER': {('World', '2012M01'): 8040.47,
220+
('World', '2011M12'): 7565.48,
221+
('World', '2011M11'): 7581.02,
222+
('World', '2011M10'): 7394.19,
223+
('World', '2011M09'): 8300.14,
224+
('World', '2011M08'): 9000.76,
225+
('World', '2011M07'): 9650.46,
226+
('World', '2011M06'): 9066.85,
227+
('World', '2011M05'): 8959.90,
228+
('World', '2011M04'): 9492.79,
229+
('World', '2011M03'): 9503.36,
230+
('World', '2011M02'): 9867.60,
231+
('World', '2011M01'): 9555.70}}
232+
expected = pd.DataFrame(expected)
233+
# Round, to ignore revisions to data.
234+
expected = np.round(expected, decimals=-3)
235+
expected = expected.sort_index()
236+
cntry_codes = 'ALL'
237+
inds = 'COPPER'
238+
result = download(country=cntry_codes, indicator=inds,
239+
start=2011, end=2012, freq='M', errors='ignore')
240+
result = result.sort_index()
241+
result = np.round(result, decimals=-3)
242+
243+
expected.index.names = ['country', 'year']
244+
tm.assert_frame_equal(result, expected)
245+
246+
result = WorldBankReader(inds, countries=cntry_codes, start=2011,
247+
end=2012, freq='M', errors='ignore').read()
248+
result = result.sort_index()
249+
result = np.round(result, decimals=-3)
250+
tm.assert_frame_equal(result, expected)
251+
252+
def test_wdi_download_quarterly(self):
253+
code = 'DT.DOD.PUBS.CD.US'
254+
expected = {code: {('Albania', '2012Q1'): 3240539817.18,
255+
('Albania', '2011Q4'): 3213979715.15,
256+
('Albania', '2011Q3'): 3187681048.95,
257+
('Albania', '2011Q2'): 3248041513.86,
258+
('Albania', '2011Q1'): 3137210567.92}}
259+
expected = pd.DataFrame(expected)
260+
# Round, to ignore revisions to data.
261+
expected = np.round(expected, decimals=-3)
262+
expected = expected.sort_index()
263+
cntry_codes = 'ALB'
264+
inds = 'DT.DOD.PUBS.CD.US'
265+
result = download(country=cntry_codes, indicator=inds,
266+
start=2011, end=2012, freq='Q', errors='ignore')
267+
result = result.sort_index()
268+
result = np.round(result, decimals=-3)
269+
270+
expected.index.names = ['country', 'year']
271+
tm.assert_frame_equal(result, expected)
272+
273+
result = WorldBankReader(inds, countries=cntry_codes, start=2011,
274+
end=2012, freq='Q', errors='ignore').read()
275+
result = result.sort_index()
276+
result = np.round(result, decimals=-1)
277+
tm.assert_frame_equal(result, expected)

pandas_datareader/wb.py

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ class WorldBankReader(_BaseReader):
116116
_format = 'json'
117117

118118
def __init__(self, symbols=None, countries=None,
119-
start=None, end=None,
119+
start=None, end=None, freq=None,
120120
retry_count=3, pause=0.001, session=None, errors='warn'):
121121

122122
if symbols is None:
@@ -144,6 +144,14 @@ def __init__(self, symbols=None, countries=None,
144144
warnings.warn('Non-standard ISO '
145145
'country codes: %s' % tmp, UserWarning)
146146

147+
freq_symbols = ['M', 'Q', 'A', None]
148+
149+
if freq not in freq_symbols:
150+
msg = 'The frequency `{0}` is not in the accepted ' \
151+
'list.'.format(freq)
152+
raise ValueError(msg)
153+
154+
self.freq = freq
147155
self.countries = countries
148156
self.errors = errors
149157

@@ -155,8 +163,18 @@ def url(self):
155163

156164
@property
157165
def params(self):
158-
return {'date': '{0}:{1}'.format(self.start.year, self.end.year),
159-
'per_page': 25000, 'format': 'json'}
166+
if self.freq == 'M':
167+
return {'date': '{0}M{1:02d}:{2}M{3:02d}'.format(self.start.year,
168+
self.start.month, self.end.year, self.end.month),
169+
'per_page': 25000, 'format': 'json'}
170+
elif self.freq == 'Q':
171+
return {'date': '{0}Q{1}:{2}Q{3}'.format(self.start.year,
172+
self.start.quarter, self.end.year,
173+
self.end.quarter), 'per_page': 25000,
174+
'format': 'json'}
175+
else:
176+
return {'date': '{0}:{1}'.format(self.start.year, self.end.year),
177+
'per_page': 25000, 'format': 'json'}
160178

161179
def read(self):
162180
try:
@@ -331,7 +349,7 @@ def search(self, string='gdp.*capi', field='name', case=False):
331349
return out
332350

333351

334-
def download(country=None, indicator=None, start=2003, end=2005,
352+
def download(country=None, indicator=None, start=2003, end=2005, freq=None,
335353
errors='warn', **kwargs):
336354
"""
337355
Download data series from the World Bank's World Development Indicators
@@ -357,6 +375,11 @@ def download(country=None, indicator=None, start=2003, end=2005,
357375
end: int
358376
Last year of the data series (inclusive)
359377
378+
freq: str
379+
frequency or periodicity of the data to be retrieved (e.g. 'M' for
380+
monthly, 'Q' for quarterly, and 'A' for annual). None defaults to
381+
annual.
382+
360383
errors: str {'ignore', 'warn', 'raise'}, default 'warn'
361384
Country codes are validated against a hardcoded list. This controls
362385
the outcome of that validation, and attempts to also apply
@@ -375,7 +398,7 @@ def download(country=None, indicator=None, start=2003, end=2005,
375398
376399
"""
377400
return WorldBankReader(symbols=indicator, countries=country,
378-
start=start, end=end, errors=errors,
401+
start=start, end=end, freq=freq, errors=errors,
379402
**kwargs).read()
380403

381404

0 commit comments

Comments
 (0)