Last active
July 29, 2018 13:06
-
-
Save wildart/ed1ea59ce72de04b7bdfd3d650e71124 to your computer and use it in GitHub Desktop.
parser-rosstat-doc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Requires to install pandas & pywin32, and of course MS Word installed. | |
import sys | |
import os | |
import win32com.client | |
import pandas as pd | |
import re | |
import numpy as np | |
JUNK_SYMBOLS = r'[\x07|\t|\x0b|\r|\x0c]' | |
def get_float(s): | |
if len(s) == 0: | |
return np.nan | |
# replace comma | |
s = s.strip().replace(',', '.') | |
s = re.sub(r'[^\d|.|)]', '', s) | |
if len(s) == 0: | |
return np.nan | |
if s[-1] == ')': | |
s = s[:-2] | |
try: | |
return float(s) | |
except ValueError: | |
return np.nan | |
def clean_index(scell): | |
scell = re.sub(r'\s{2,}', ' ', scell) # replace multiple spaces | |
scell = scell.replace('\n', ' ') # remove new lines | |
#try to find '/' for english part | |
sidx = scell.find('/') | |
if sidx < 0: | |
return None | |
idx = scell.split('/')[-1].strip() # get english part | |
return idx | |
def find_first_filled_col(rng): | |
i = 1 | |
while True: | |
cl = rng.Cells(i) | |
txt = cl.Range.Text | |
if len(re.sub(JUNK_SYMBOLS, '', txt).strip()) > 0 and cl.ColumnIndex == 1: | |
return i | |
i += 1 | |
docname = 'tab.doc' if len(sys.argv) < 2 else sys.argv[1] | |
docfile = os.path.realpath(docname) | |
# open word | |
word = win32com.client.Dispatch("Word.Application") | |
#word.visible = True | |
word.visible = False | |
wb = word.Documents.Open(docfile) | |
doc = word.ActiveDocument | |
# setup data frame | |
indexed = ['Category', 'Year'] | |
header = ['YTD', 'Q1', 'Q2', 'Q3', 'Q4', 'Jan.', 'Feb.', 'Mar.', 'Apr.', 'May', 'June', 'July', 'Aug.', 'Sept.', 'Oct.', 'Nov.', 'Dec.'] | |
df = pd.DataFrame(columns=indexed+header) | |
df.set_index(indexed, inplace=True) | |
global_index = [] | |
try: | |
# loop through tables | |
total_tables = len(doc.Tables) | |
for tidx in range(0, total_tables-1): | |
print(tidx) | |
table = doc.Tables[tidx] | |
rc = table.Rows.Count | |
cc = table.Columns.Count | |
rng = table.Range | |
i = find_first_filled_col(rng) | |
index = [] | |
row = [] | |
c = 1 | |
cl = rng.Cells(i) | |
for i in range(i, rng.Cells.Count): | |
clnext = rng.Cells(i+1) | |
txt = re.sub(JUNK_SYMBOLS, '', cl.Range.Text.strip()) # remove special symbols | |
# if len(txt.strip()) == 0: # if cell is empty | |
# cl = clnext | |
# continue | |
# check description of table part to construct index | |
if cl.ColumnIndex == 1: | |
if re.match(r'^(\d+\.\d+\.|\D)+', txt) is not None: | |
if re.match(r'^(\d+\.\d+\.\s)+', txt) is not None: # match subsection <N.N.> | |
print('cat: {0}'.format(txt)) | |
global_index = [] | |
sidx = clean_index(txt) | |
print('index: {0}'.format(sidx)) | |
if sidx is not None: | |
index.append(sidx) | |
else: | |
try: | |
year = int(txt[:4]) | |
row.append(year) | |
except ValueError: | |
print("c:{0} = {1}".format(i, txt)) | |
cl = clnext | |
continue | |
# data | |
if len(index) > 0: #merge with global index | |
if len(global_index) == 0: | |
global_index = index.copy() | |
elif len(global_index) == 1: | |
global_index += index | |
else: | |
global_index[-len(index):] = index | |
print(global_index) | |
index = [] | |
val = get_float(txt) | |
if len(row) == 0 and val is np.nan: | |
cl = clnext | |
continue | |
else: | |
row.append(val) | |
c += 1 | |
if c == cc: # reached last column | |
if row[0] is not np.nan: | |
midx = (', '.join(global_index), int(row[0])) | |
if cc == 6: | |
rr = row[1:] + [np.nan for i in range(0, len(header)-cc+1)] | |
elif cc == 13 or cc == 14: | |
rr = [np.nan for i in range(0, len(header)-cc+1)] + row[1:] | |
else: | |
rr = row[1:] | |
try: | |
df.loc[midx,:] = rr | |
except: | |
print(midx) | |
print(rr) | |
row = [] | |
c = 1 | |
cl = clnext | |
if len(row) == 0: # drop last cell that does not fit into row | |
continue | |
# last cell | |
txt = re.sub(JUNK_SYMBOLS, '', cl.Range.Text) | |
row.append(get_float(txt)) | |
try: | |
midx = (', '.join(global_index), int(row[0])) | |
except: | |
print(row) | |
if cc == 6: | |
rr = row[1:] + [np.nan for i in range(0, len(header)-cc+1)] | |
elif cc == 13 or cc == 14: | |
rr = [np.nan for i in range(0, len(header)-cc+1)] + row[1:] | |
else: | |
rr = row[1:] | |
df.loc[midx,:] = rr | |
except: | |
print("Unexpected error:", sys.exc_info()[0]) | |
raise | |
finally: | |
df.to_msgpack("tab.msgpack") | |
word.Quit(0) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
>>> pd.read_msgpack("tab.msgpack") | |
YTD Q1 Q2 Q3 Q4 Jan. Feb. Mar. Apr. May June July Aug. Sept. Oct. Nov. Dec. | |
Categoty Year | |
Gross domestic product1), GDP, bln rubles 1999 4823.0 901.0 1102.0 1373.0 1447.0 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN | |
2000 7306.0 1527.0 1697.0 2038.0 2044.0 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN | |
2001 8944.0 1901.0 2105.0 2488.0 2450.0 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN | |
2002 10831.0 2262.0 2529.0 3013.0 3027.0 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN | |
2003 13208.0 2851.0 3102.0 3600.0 3655.0 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN | |
2004 17027.0 3516.0 3972.0 4594.0 4945.0 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN | |
2005 21610.0 4459.0 5078.0 5845.0 6228.0 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN | |
2006 26917.0 5793.0 6368.0 7276.0 7480.0 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN | |
2007 33248.0 6780.0 7768.0 8903.0 9797.0 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN | |
2008 41277.0 8878.0 10238.0 11542.0 10619.0 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN | |
2009 38807.0 8335.0 9245.0 10411.0 10816.0 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN | |
2010 46308.0 9996.0 10977.0 12086.0 13249.0 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN | |
2011 59698.0 12844.0 14314.0 15663.0 16877.0 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN | |
2012 66927.0 14925.0 16149.0 17442.0 18411.0 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN | |
2013 71017.0 15892.0 17015.0 18543.0 19567.0 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN | |
2014 79200.0 17139.0 18884.0 20407.0 21515.0 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN | |
2015 83233.0 18210.0 19284.0 21294.0 22016.0 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN | |
2016 86044.0 18561.0 19979.0 22190.0 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN | |
Gross domestic product1), percent of correspond... 1999 106.4 98.1 103.1 111.4 112.0 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN | |
2000 110.0 111.4 110.2 110.5 108.2 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN | |
2001 105.1 104.7 105.0 106.0 104.5 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN | |
2002 104.7 103.8 104.4 104.4 106.2 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN | |
2003 107.3 107.5 107.9 106.1 107.6 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN | |
2004 107.2 107.2 108.0 107.3 106.2 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN | |
2005 106.4 105.6 106.0 106.0 107.8 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN | |
2006 108.2 107.3 108.1 108.2 108.9 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN | |
2007 108.5 108.1 108.6 108.2 109.2 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN | |
2008 105.2 109.2 107.9 106.4 98.7 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN | |
2009 92.2 90.8 88.8 91.4 97.4 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN | |
2010 104.5 104.1 105.0 103.8 105.1 NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN | |
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... | |
Consumer price index percent of previous month,... 2004 NaN NaN NaN NaN NaN 103.3 101.9 100.4 100.6 100.1 101.3 101.5 98.4 98.4 101.1 102.1 103.1 | |
2005 NaN NaN NaN NaN NaN 102.9 102.2 102.8 102.8 101.8 101.4 100.2 95.9 96.5 100 101.8 102.2 | |
2006 NaN NaN NaN NaN NaN 104.3 105.5 101.2 99.8 100.5 100.4 101.8 96.6 96.1 99.6 101.5 102.1 | |
2007 NaN NaN NaN NaN NaN 102.2 101.2 101.2 100.8 102.2 104.8 103.6 96 99 104 102.8 102.7 | |
2008 NaN NaN NaN NaN NaN 104.3 103.3 102.7 103.9 104.1 100.9 98.8 96.3 98.5 101.4 101.3 101.1 | |
2009 NaN NaN NaN NaN NaN 102 101.5 100.6 100.4 101.2 101.4 101.5 96.6 96.2 98.2 100.3 101.1 | |
2010 NaN NaN NaN NaN NaN 102.4 102.2 101.4 100.4 101.5 101.2 100.4 100.7 103 100.9 102.2 104.2 | |
2011 NaN NaN NaN NaN NaN 107.5 102 100.7 99.8 98.8 98.4 97.4 93.5 95.9 99.2 100.4 100.9 | |
2012 NaN NaN NaN NaN NaN 100.7 100.8 100.7 100.4 101 103.8 102.1 97.6 98.3 100 100.8 101.5 | |
2013 NaN NaN NaN NaN NaN 101.9 101.2 100.9 102.1 103.8 103.2 99.7 95.8 97.2 101.6 101.2 101.2 | |
2014 NaN NaN NaN NaN NaN 102.2 102.6 102.7 101.9 103.1 101.4 96.9 94.9 99.3 101.6 103.1 105.1 | |
2015 NaN NaN NaN NaN NaN 108.3 103.8 101.2 100.3 101 99.2 99.3 95.2 98.1 100 100.9 101.2 | |
2016 NaN NaN NaN NaN NaN 101.4 100.6 100.2 100.6 101.7 102.1 100.1 97.3 97.8 100.2 100.9 100.9 | |
Consumer price index percent of previous month,... 2000 NaN NaN NaN NaN NaN 102.2 102.5 101.9 102.1 105.1 109.4 111.5 107.8 105 106.4 109.6 113.2 | |
2001 NaN NaN NaN NaN NaN 104.6 108.1 110.2 112.8 116.8 120.2 117.9 113.5 111 111.7 114.6 118.8 | |
2002 NaN NaN NaN NaN NaN 105.1 106.2 105.9 107.5 111.7 110.9 110.7 107.2 104.2 105 108.4 112.8 | |
2003 NaN NaN NaN NaN NaN 104 106.1 106.8 108.6 109.6 111 111.1 104.9 102.1 102.9 105.1 107.6 | |
2004 NaN NaN NaN NaN NaN 103.3 105.3 105.7 106.3 106.5 107.8 109.4 107.7 105.9 107.1 109.4 112.7 | |
2005 NaN NaN NaN NaN NaN 102.9 105.2 108.1 111.1 113.1 114.7 115 110.3 106.4 106.4 108.3 110.7 | |
2006 NaN NaN NaN NaN NaN 104.3 110 111.3 111.1 111.6 112.1 114 110.1 105.9 105.4 107 109.2 | |
2007 NaN NaN NaN NaN NaN 102.2 103.4 104.7 105.5 107.9 113.1 117.1 112.4 111.3 115.8 119 122.3 | |
2008 NaN NaN NaN NaN NaN 104.3 107.7 110.6 114.9 119.6 120.6 119.2 114.8 113.1 114.7 116.2 117.5 | |
2009 NaN NaN NaN NaN NaN 102 103.5 104.1 104.6 105.9 107.3 108.9 105.2 101.1 99.3 99.6 100.7 | |
2010 NaN NaN NaN NaN NaN 102.4 104.7 106.2 106.6 108.2 109.5 110 110.8 114.1 115.2 117.7 122.7 | |
2011 NaN NaN NaN NaN NaN 107.5 109.7 110.4 110.3 109 107.2 104.4 97.6 93.5 92.8 93.2 93.9 | |
2012 NaN NaN NaN NaN NaN 100.7 101.5 102.2 102.6 103.7 107.6 109.9 107.3 105.4 105.4 106.2 107.8 | |
2013 NaN NaN NaN NaN NaN 101.9 103 103.9 106.1 110.1 113.6 113.3 108.6 105.5 107.2 108.5 109.9 | |
2014 NaN NaN NaN NaN NaN 102.2 104.8 107.7 109.7 113.1 114.7 111.2 105.5 104.7 106.4 109.8 115.3 | |
2015 NaN NaN NaN NaN NaN 108.3 112.4 113.7 114.1 115.2 114.3 113.5 108 106 106 106.9 108.2 | |
2016 NaN NaN NaN NaN NaN 101.4 102.1 102.2 102.9 104.6 106.7 106.8 103.9 101.6 101.8 102.7 103.5 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment