Repository: modin-project/modin

Issue:
read_csv_glob can't handle parse_dates with lists that include lists that include ints
### System information
- **OS Platform and Distribution (e.g., Linux Ubuntu 16.04)**: MacOS Monterey 12.2.1
- **Modin version** (`modin.__version__`): latest source
- **Python version**: 3.9.9
- **Code we can use to reproduce**:

```python
import pandas
import modin.experimental.pandas as pd
pdf = pandas.DataFrame([[3, 4]])
df.to_csv("/tmp/data.csv", index=False)
parse_dates=[[0, 1]]
# This works.
pandas.read_csv("/tmp/data.csv", parse_dates=parse_dates)
# This raises TypeError:
pd.read_csv_glob("/tmp/data.csv", parse_dates=parse_dates)
```

<!--
You can obtain the Modin version with

python -c "import modin; print(modin.__version__)"
-->

### Describe the problem
Lists within the parse_dates list are sequences of CSV columns that are parsed together as a single date column. They can be a list of either string column names or integer column indices. e.g. if parse_dates is [[1, 2]] and columns at indices 1 and 2 are "b" and "c", the output dataframe has the single date column "b_c". If parse_dates is [["a", 1]] and the column at index 1 is named "b", the output dataframe has the single date column "a_b".

### Source code / logs
<details>
<summary>Show stack trace.</summary>

```
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Input In [6], in <module>
----> 1 pd.read_csv_glob("/tmp/data.csv", parse_dates=[[0, 1]])

File ~/modin/modin/experimental/pandas/io.py:183, in _make_parser_func.<locals>.parser_func(filepath_or_buffer, sep, delimiter, header, names, index_col, usecols, squeeze, prefix, mangle_dupe_cols, dtype, engine, converters, true_values, false_values, skipinitialspace, skiprows, nrows, na_values, keep_default_na, na_filter, verbose, skip_blank_lines, parse_dates, infer_datetime_format, keep_date_col, date_parser, dayfirst, cache_dates, iterator, chunksize, compression, thousands, decimal, lineterminator, quotechar, quoting, escapechar, comment, encoding, encoding_errors, dialect, error_bad_lines, warn_bad_lines, on_bad_lines, skipfooter, doublequote, delim_whitespace, low_memory, memory_map, float_precision, storage_options)
    180     f_locals["sep"] = "\t"
    182 kwargs = {k: v for k, v in f_locals.items() if k in _pd_read_csv_signature}
--> 183 return _read(**kwargs)

File ~/modin/modin/experimental/pandas/io.py:229, in _read(**kwargs)
    226 Engine.subscribe(_update_engine)
    228 try:
--> 229     pd_obj = FactoryDispatcher.read_csv_glob(**kwargs)
    230 except AttributeError:
    231     raise AttributeError("read_csv_glob() is only implemented for pandas on Ray.")

File ~/modin/modin/core/execution/dispatching/factories/dispatcher.py:190, in FactoryDispatcher.read_csv_glob(cls, **kwargs)
    187 @classmethod
    188 @_inherit_docstrings(factories.ExperimentalPandasOnRayFactory._read_csv_glob)
    189 def read_csv_glob(cls, **kwargs):
--> 190     return cls.__factory._read_csv_glob(**kwargs)

File ~/modin/modin/core/execution/dispatching/factories/factories.py:523, in ExperimentalPandasOnRayFactory._read_csv_glob(cls, **kwargs)
    516 @classmethod
    517 @doc(
    518     _doc_io_method_raw_template,
   (...)
    521 )
    522 def _read_csv_glob(cls, **kwargs):
--> 523     return cls.io_cls.read_csv_glob(**kwargs)

File ~/modin/modin/core/io/text/csv_glob_dispatcher.py:245, in CSVGlobDispatcher._read(cls, filepath_or_buffer, **kwargs)
    243 if isinstance(parse_dates, list) and isinstance(parse_dates[0], list):
    244     for group in parse_dates:
--> 245         new_col_name = "_".join(group)
    246         column_names = column_names.drop(group).insert(0, new_col_name)
    247 # Check if it is a dictionary

TypeError: sequence item 0: expected str instance, int found
```
</details>



Discussion:

Resolving patch:
diff --git a/modin/core/io/text/csv_glob_dispatcher.py b/modin/core/io/text/csv_glob_dispatcher.py
--- a/modin/core/io/text/csv_glob_dispatcher.py
+++ b/modin/core/io/text/csv_glob_dispatcher.py
@@ -251,10 +251,9 @@ def _read(cls, filepath_or_buffer, **kwargs):
                     # named "b", the output dataframe has the single date
                     # column "a_b".
                     if isinstance(date, list):
-                        # TODO(https://github.com/modin-project/modin/issues/4310):
-                        # Handle parse_dates with lists that include lists that
-                        # include ints. This code assumes that all lists with
-                        # parse_dates are lists of column names.
+                        for i, part in enumerate(date):
+                            if isinstance(part, int):
+                                date[i] = column_names[part]
                         new_col_name = "_".join(date)
                         column_names = column_names.drop(date).insert(0, new_col_name)
             elif isinstance(parse_dates, dict):


Test patch:
diff --git a/modin/pandas/test/utils.py b/modin/pandas/test/utils.py
--- a/modin/pandas/test/utils.py
+++ b/modin/pandas/test/utils.py
@@ -129,6 +129,8 @@
     "list_of_single_string": ["timestamp"],
     "list_of_list_of_strings": [["year", "month", "date"]],
     "list_of_string_and_list_of_strings": ["timestamp", ["year", "month", "date"]],
+    "list_of_list_of_ints": [[1, 2, 3]],
+    "list_of_list_of_strings_and_ints": [["year", 2, "date"]],
     "empty_list": [],
     "nonexistent_string_column": ["z"],
     "nonexistent_int_column": [99],