Abstract tabular dataset loading by mttk · Pull Request #274 · TakeLab/podium · GitHub
Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 25 additions & 65 deletions podium/datasets/arrow.py
2 changes: 1 addition & 1 deletion podium/datasets/impl/catacx_comments_dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ def _create_examples(dir_path, fields):
A list of examples containing comments from the Catacx dataset.
"""
example_factory = ExampleFactory(fields)
with open(dir_path, encoding="utf8") as f:
with open(os.path.expanduser(dir_path), encoding="utf8") as f:
ds = json.load(f)

examples = []
Expand Down
2 changes: 1 addition & 1 deletion podium/datasets/impl/snli_dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ def _create_examples(file_path, fields):
example_factory = ExampleFactory(fields)
examples = []

with open(file=file_path, encoding="utf8") as in_file:
with open(file=os.path.expanduser(file_path), encoding="utf8") as in_file:
for line in in_file:
examples.append(example_factory.from_json(line))
return examples
Expand Down
134 changes: 86 additions & 48 deletions podium/datasets/tabular_dataset.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import csv
import os
from typing import Callable, Dict, List, Optional, Union

from podium.datasets.dataset import Dataset
from podium.field import Field

from .example_factory import ExampleFactory

Expand All @@ -14,12 +16,12 @@ class TabularDataset(Dataset):

def __init__(
self,
path,
fields,
format="csv",
line2example=None,
skip_header=False,
csv_reader_params={},
path: str,
fields: Union[Dict[str, Field], List[Field]],
format: str = "csv",
line2example: Optional[Callable] = None,
skip_header: bool = False,
csv_reader_params: Optional[Dict] = None,
**kwargs,
):
"""
Expand Down Expand Up @@ -83,58 +85,94 @@ def __init__(
If format is "JSON" and skip_header is True.
"""

format = format.lower()

with open(os.path.expanduser(path), encoding="utf8") as f:

# Skip header prior to custom line2example in case
# the header is in a different format so we don't
# cause an error.
if skip_header:
if format == "json":
raise ValueError(
f"When using a {format} file, skip_header \
must be False."
)
elif format in {"csv", "tsv", "custom"} and isinstance(fields, dict):
raise ValueError(
f"When using a dict to specify fields with a {format} "
"file, skip_header must be False and the file must "
"have a header."
)

# skip the header
next(f)

if line2example is not None:
reader = (line2example(line) for line in f)
format = "custom"
elif format in {"csv", "tsv"}:
delimiter = "," if format == "csv" else "\t"
reader = csv.reader(f, delimiter=delimiter, **csv_reader_params)
elif format == "json":
reader = f
else:
raise ValueError(f"Invalid format: {format}")

# create a list of examples
examples = create_examples(reader, format, fields)

# create a Dataset with lists of examples and fields
examples = _load_tabular_file(
path, fields, format, line2example, skip_header, csv_reader_params
)
# Make the examples concrete here by casting to list
examples = list(examples)

super(TabularDataset, self).__init__(examples, fields, **kwargs)
self.finalize_fields()


def create_examples(reader, format, fields):
def _load_tabular_file(
path, fields, format, line2example, skip_header, csv_reader_params
):
"""
Loads examples as a generator from a dataset in tabular format.

Abstracted from TabularDataset due to duplicate usage in ArrowDataset.
Parameters same as in TabularDataset constructor.
"""

with open(os.path.expanduser(path), encoding="utf8", newline="") as f:
# create a list of examples
reader, format = _initialize_tabular_reader(
f, format, fields, line2example, skip_header, csv_reader_params
)
examples = _create_examples(reader, format, fields)
yield from examples


def _initialize_tabular_reader(
file, format, fields, line2example, skip_header, csv_reader_params
):
"""
Initializes the input stream from a file.

In case of using a custom format handled by line2example, lazily applies the
row transfromation on the data.
"""

format = format.lower()

# Skip header prior to custom line2example in case
# the header is in a different format so we don't
# cause an error.
if skip_header:
if format == "json":
raise ValueError(
f"When using a {format} file, skip_header \
must be False."
)
elif format in {"csv", "tsv", "custom"} and isinstance(fields, dict):
raise ValueError(
f"When using a dict to specify fields with a {format} "
"file, skip_header must be False and the file must "
"have a header."
)

# skip the header
next(file)

if line2example is not None:
reader = (line2example(line) for line in file)
format = "custom"
Comment thread
mttk marked this conversation as resolved.
elif format in {"csv", "tsv"}:
delimiter = "," if format == "csv" else "\t"
if csv_reader_params is None:
csv_reader_params = {}
reader = csv.reader(file, delimiter=delimiter, **csv_reader_params)
elif format == "json":
reader = file
else:
raise ValueError(f"Invalid format: {format}")

return reader, format


def _create_examples(reader, format, fields):
"""
Creates a list of examples from the given line reader and fields (see
TabularDataset.__init__ docs for more info on the fields).

Parameters
----------
reader
A reader object that reads one line at a time. Yields either strings
(when format is JSON) or lists of values (when format is CSV/TSV).
A reader object that reads one line at a time. Yields strings
(when format is JSON) or lists of values (when format is CSV/TSV)
or a sequence of pre-transformed lines if a custom format is used
via the `line2example` argument.
format : str
Format of the data file that is being read. Can be either CSV,
TSV or JSON.
Expand Down Expand Up @@ -178,4 +216,4 @@ def create_examples(reader, format, fields):
# map each line from the reader to an example
examples = map(make_example, reader)

return list(examples)
return examples
6 changes: 4 additions & 2 deletions podium/vectorizers/vectorizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,11 @@ def __init__(
max_vectors : int, optional
maximum number of vectors to load in memory
"""
self._path = path
self._path = os.path.expanduser(path) if path is not None else path
self._default_vector_function = default_vector_function
self._cache_path = cache_path
self._cache_path = (
os.path.expanduser(cache_path) if cache_path is not None else cache_path
)
self._max_vectors = max_vectors

@abstractmethod
Expand Down
2 changes: 1 addition & 1 deletion tests/datasets/test_arrow.py