Skip to content

Commit 32bdfc0

Browse files
sstruziksambles
andauthored
add pyarrow dtype to oed json (#262)
* add pyarrow dtype to oed json * add support backend dtype * drop 3.8 support * set custom ENV_ODS_SCHEMA_PATH * fixup * test ci * test ci * retest-ci * test ci * fixup --------- Co-authored-by: Sam Gamble <hexadessa@gmail.com>
1 parent 646da1a commit 32bdfc0

1 file changed

Lines changed: 40 additions & 38 deletions

File tree

utils/gen-json.py

Lines changed: 40 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -6,36 +6,33 @@
66
import os
77
import click
88

9-
pd_converter = {
10-
"0 or 1": "Int8",
11-
"bigint": "Int64",
12-
"binary": "Int8",
13-
"bit": "Int8",
14-
"char": "category",
15-
"date": "category",
16-
"datetime": "category",
17-
"decimal": "float64",
18-
"float": "float64",
19-
"int": "Int64",
20-
"nchar": "category",
21-
"nvarchar": "category",
22-
"real": "float64",
23-
"smalldatetime": "category",
24-
"smallint": "Int32",
25-
"tinyint": "Int32",
26-
"uniqueidentifier": "category",
27-
"varbinary": "bytes",
28-
"varchar": "category",
29-
}
30-
31-
dtype_to_python = {
32-
"Int8": int,
33-
"Int32": int,
34-
"Int64": int,
35-
"bytes": lambda x: bytes(x, "utf-8"),
36-
"float64": float,
37-
"category": str,
38-
}
9+
# convertion map between OED, numpy_nullable, pyarrow, python
10+
_converter_header = ["OED Data Type", "numpy_nullable", "pyarrow", "python"]
11+
_converter_list = [
12+
["0 or 1", "Int8", "int8[pyarrow]", int],
13+
["bigint", "Int64", "int64[pyarrow]", int],
14+
["binary", "Int8", "int8[pyarrow]", int],
15+
["bit", "Int8", "int8[pyarrow]", int],
16+
["char", "category", "string[pyarrow]", str],
17+
["date", "category", "string[pyarrow]", str],
18+
["datetime", "category", "string[pyarrow]", str],
19+
["decimal", "float64", "float64[pyarrow]", float],
20+
["float", "float64", "float64[pyarrow]", float],
21+
["int", "Int64", "int64[pyarrow]", int],
22+
["nchar", "category", "string[pyarrow]", str],
23+
["nvarchar", "category", "string[pyarrow]", str],
24+
["real", "float64", "float64[pyarrow]", float],
25+
["smalldatetime", "category", "string[pyarrow]", str],
26+
["smallint", "Int32", "int32[pyarrow]", int],
27+
["tinyint", "Int32", "int32[pyarrow]", int],
28+
["uniqueidentifier", "category", "string[pyarrow]", str],
29+
["varbinary", "bytes", "string[pyarrow]", lambda x: bytes(x, "utf-8")],
30+
["varchar", "category", "string[pyarrow]", str],
31+
]
32+
converter_df = pd.DataFrame(_converter_list, columns=_converter_header)
33+
pd_converter = converter_df[["OED Data Type", "numpy_nullable"]].set_index("OED Data Type")["numpy_nullable"].to_dict()
34+
pa_converter = converter_df[["OED Data Type", "pyarrow"]].set_index("OED Data Type")["pyarrow"].to_dict()
35+
dtype_to_python = converter_df[["OED Data Type", "python"]].set_index("OED Data Type")["python"].to_dict()
3936

4037
# Directory containing the CSV files
4138
source_csv_default = pathlib.Path(os.path.dirname(os.path.realpath(__file__))).parent.joinpath('OpenExposureData')
@@ -63,6 +60,7 @@ def _read_oed_data(sheet_name, basepath=source_csv_dir):
6360

6461

6562
ods_schema = {}
63+
ods_schema["backend_dtype"] = ['pd_dtype', 'pa_dtype']
6664
ods_schema["input_fields"] = get_ods_input_fields(_read_oed_data("OEDInputFields"))
6765
ods_schema["perils"] = get_ods_perils(_read_oed_data("PerilValues"), _read_oed_data("PerilsCovered"))
6866
ods_schema["occupancy"] = get_occupancy(_read_oed_data("OccupancyValues"))
@@ -83,7 +81,6 @@ def _read_oed_data(sheet_name, basepath=source_csv_dir):
8381
with open(output_path, "w") as fp:
8482
json.dump(ods_schema, fp, indent=" ")
8583

86-
8784
print(f"JSON OED specification has been created from dir '{source_csv_dir}'. Output saved to '{output_path}'")
8885

8986

@@ -102,20 +99,22 @@ def get_ods_input_fields(ods_fields_df):
10299
ods_fields_df = ods_fields_df.assign(
103100
pd_dtype=ods_fields_df["Data Type"]
104101
.str.split("(", n=1, expand=True)[0]
105-
.map(pd_converter)
102+
.map(pd_converter),
103+
pa_dtype=ods_fields_df["Data Type"]
104+
.str.split("(", n=1, expand=True)[0]
105+
.map(pa_converter)
106106
).rename(columns={"File Name": "File Names"})
107107
ods_fields_df["Case Insensitive Field Name"] = ods_fields_df[
108108
"Input Field Name"
109109
].str.lower()
110110

111111
# check that to Data Type is missing from our converter
112-
if ods_fields_df["pd_dtype"].isna().any():
112+
if ods_fields_df["pd_dtype"].isna().any() or ods_fields_df["pa_dtype"].isna().any():
113113
raise ValueError(
114-
f"missing pd_dtype for:\n"
115-
f"""{ods_fields_df.loc[ods_fields_df['pd_dtype'].isna(),
114+
f"missing dtype for:\n"
115+
f"""{ods_fields_df.loc[(ods_fields_df['pd_dtype'].isna()) | (ods_fields_df["pa_dtype"].isna()),
116116
['File Name', 'Input Field Name', 'Type & Description', 'Data Type']]}"""
117117
)
118-
119118
# split ods_fields per File Name
120119
split_df = ods_fields_df["File Names"].str.split(";").apply(pd.Series).stack()
121120
split_df = (
@@ -125,7 +124,7 @@ def get_ods_input_fields(ods_fields_df):
125124

126125
ods_fields_df["Valid value range"] = ods_fields_df.apply(
127126
lambda row: extract_valid_value_range(
128-
row["Valid value range"], dtype_to_python[row["pd_dtype"]]
127+
row["Valid value range"], dtype_to_python[row["Data Type"].split("(", 1)[0]]
129128
),
130129
axis=1,
131130
)
@@ -271,7 +270,10 @@ def get_cr_field(cr_field_df):
271270
cr_field_df = cr_field_df.assign(
272271
pd_dtype=cr_field_df["Data Type"]
273272
.str.split("(", n=1, expand=True)[0]
274-
.map(pd_converter)
273+
.map(pd_converter),
274+
pa_dtype=cr_field_df["Data Type"]
275+
.str.split("(", n=1, expand=True)[0]
276+
.map(pa_converter)
275277
).rename(columns={"File Name": "File Names"})
276278

277279
# split ods_fields per File Name

0 commit comments

Comments
 (0)