Skip to content

Text Exporter

Bases: DataFrameExporter


              flowchart TD
              metaframe.src.dataframe.exporter.txt.TxtExporter[TxtExporter]
              metaframe.src.dataframe.exporter.base.DataFrameExporter[DataFrameExporter]

                              metaframe.src.dataframe.exporter.base.DataFrameExporter --> metaframe.src.dataframe.exporter.txt.TxtExporter
                


              click metaframe.src.dataframe.exporter.txt.TxtExporter href "" "metaframe.src.dataframe.exporter.txt.TxtExporter"
              click metaframe.src.dataframe.exporter.base.DataFrameExporter href "" "metaframe.src.dataframe.exporter.base.DataFrameExporter"
            
Source code in metaframe/src/dataframe/exporter/txt.py
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
class TxtExporter(DataFrameExporter):

    Opts = ExportOptionsTxt

    def prepare_opts(self, *args, **kwargs) -> Opts:
        opts = super().prepare_opts(*args, **kwargs)
        opts.extensive = False # Disable for Text output, how should we do it?
        return opts

    def export(self) -> None:
        """
        Writes DataFrame to text with Excel-compatible MultiIndex formatting.

        Tables are written directly. MultiIndex DataFrames are formatted into a
        three-part layout compatible with Excel-style MetaFrame exports.
        """
        if self.is_table:
            return self.df.to_csv(self.opts.output, index=self.opts.index, header=self.opts.header, sep=self.opts.sep, **self.opts.kwargs)
        # We have to format our DataFrame like en Excel file (without index or header)
        mfr = self.df.mf(axis=0)
        mfc = self.df.mf(axis=1)
        # Part 1: NA block (depending on number of columns in MFR) + Transposed MFC
        #part1 = pd.concat([pd.DataFrame(columns=range(self.mfr_shape[1]-1)), mfc.T.reset_index()], ignore_index=True, axis=1)
        # Part 2: MFR column names + empty cells (DF_EMPTY_CELL)
        #part2 = pd.DataFrame(mfr.columns.tolist()+[DF_EMPTY_CELL]*self.mfc_shape[0]).T
        # Part 3: MFR values + DataFrame values
        #part3 = pd.concat([mfr, pd.DataFrame(self.values)], ignore_index=True, axis=1)
        return pd.concat([
                # Part 1
                pd.concat([pd.DataFrame(columns=range(self.mfr_shape[1]-1)), mfc.T.reset_index()], ignore_index=True, axis=1), 
                # Part 2
                pd.DataFrame(mfr.columns.tolist()+[DF_EMPTY_CELL]*self.mfc_shape[0]).T, 
                # Part 3
                pd.concat([mfr, pd.DataFrame(self.df.values)], ignore_index=True, axis=1)
            ]).to_csv(self.opts.output, sep=self.opts.sep, index=False, header=False, **self.opts.kwargs)

export()

Writes DataFrame to text with Excel-compatible MultiIndex formatting.

Tables are written directly. MultiIndex DataFrames are formatted into a three-part layout compatible with Excel-style MetaFrame exports.

Source code in metaframe/src/dataframe/exporter/txt.py
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
def export(self) -> None:
    """
    Writes DataFrame to text with Excel-compatible MultiIndex formatting.

    Tables are written directly. MultiIndex DataFrames are formatted into a
    three-part layout compatible with Excel-style MetaFrame exports.
    """
    if self.is_table:
        return self.df.to_csv(self.opts.output, index=self.opts.index, header=self.opts.header, sep=self.opts.sep, **self.opts.kwargs)
    # We have to format our DataFrame like en Excel file (without index or header)
    mfr = self.df.mf(axis=0)
    mfc = self.df.mf(axis=1)
    # Part 1: NA block (depending on number of columns in MFR) + Transposed MFC
    #part1 = pd.concat([pd.DataFrame(columns=range(self.mfr_shape[1]-1)), mfc.T.reset_index()], ignore_index=True, axis=1)
    # Part 2: MFR column names + empty cells (DF_EMPTY_CELL)
    #part2 = pd.DataFrame(mfr.columns.tolist()+[DF_EMPTY_CELL]*self.mfc_shape[0]).T
    # Part 3: MFR values + DataFrame values
    #part3 = pd.concat([mfr, pd.DataFrame(self.values)], ignore_index=True, axis=1)
    return pd.concat([
            # Part 1
            pd.concat([pd.DataFrame(columns=range(self.mfr_shape[1]-1)), mfc.T.reset_index()], ignore_index=True, axis=1), 
            # Part 2
            pd.DataFrame(mfr.columns.tolist()+[DF_EMPTY_CELL]*self.mfc_shape[0]).T, 
            # Part 3
            pd.concat([mfr, pd.DataFrame(self.df.values)], ignore_index=True, axis=1)
        ]).to_csv(self.opts.output, sep=self.opts.sep, index=False, header=False, **self.opts.kwargs)

__init__(df, *args, **kwargs)

Initialize the exporter.

Parameters:

Name Type Description Default
df DataFrame

The DataFrame to export.

required
*args

Arguments used to construct the exporter-specific options dataclass. Supported keys depend on the concrete exporter.

()
**kwargs

Arguments used to construct the exporter-specific options dataclass. Supported keys depend on the concrete exporter.

()
Notes

The provided options are validated and normalized by prepare_opts before export. The original DataFrame is never modified in place.

Source code in metaframe/src/dataframe/exporter/base.py
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
def __init__(self, df: 'DataFrame', *args, **kwargs) -> None: # type: ignore  # noqa: F821
    """
    Initialize the exporter.

    Parameters
    ----------
    df : DataFrame
        The DataFrame to export.

    *args, **kwargs
        Arguments used to construct the exporter-specific
        options dataclass. Supported keys depend on the concrete exporter.

    Notes
    -----
    The provided options are validated and normalized by `prepare_opts`
    before export. The original DataFrame is never modified in place.
    """
    self.is_table = df.is_table
    self.opts = self.prepare_opts(*args, **kwargs)
    self.df = self.prepare_data(df)
    self.mfr_shape = self.set_mfr_shape()
    self.mfc_shape = self.set_mfc_shape()

set_mfr_shape()

Sets the expected MetaFrameRow shape in the export.

MetaFrameRow shape for non-tables, DataFrame number of rows & 1 (if header+index) or 0 fr tables

Source code in metaframe/src/dataframe/exporter/base.py
49
50
51
52
53
54
55
56
57
58
def set_mfr_shape(self) -> None:
    """
    Sets the expected MetaFrameRow shape in the export.

    MetaFrameRow shape for non-tables, DataFrame number of rows & 
    1 (if header+index) or 0 fr tables
    """
    if not self.is_table:
        return self.df.mf(axis=0).shape
    return (self.df.shape[0], 1 if self.opts.header and self.opts.index else 0)

set_mfc_shape()

Sets the expected MetaFrameCol shape in the export.

MetaFrameCol shape for non-tables, DataFrame number of rows & 1 (if header+index) or 0 fr tables

Source code in metaframe/src/dataframe/exporter/base.py
60
61
62
63
64
65
66
67
68
69
def set_mfc_shape(self) -> None:
    """
    Sets the expected MetaFrameCol shape in the export.

    MetaFrameCol shape for non-tables, DataFrame number of rows & 
    1 (if header+index) or 0 fr tables
    """
    if not self.is_table:
        return self.df.mf(axis=1).shape
    return (1 if self.opts.header and self.opts.index else 0, self.df.shape[1])

prepare_data(df)

Prepare a copy of the DataFrame for serialization.

The returned DataFrame is transformed to ensure it can be written and later reconstructed correctly by readers. Transformations may include:

  • resetting the index/columns
  • normalizing headers
  • converting indices/columns to MultiIndex form
  • adding MetaFrames rows unique identifiers

Parameters:

Name Type Description Default
df DataFrame
required

Returns:

Type Description
DataFrame

A modified copy of the original DataFrame ready for export.

Notes

The original DataFrame is not modified.

Source code in metaframe/src/dataframe/exporter/base.py
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
def prepare_data(self, df: 'DataFrame') -> 'DataFrame':  # type: ignore # noqa: F821
    """
    Prepare a copy of the DataFrame for serialization.

    The returned DataFrame is transformed to ensure it can be written and
    later reconstructed correctly by readers. Transformations may include:

    - resetting the index/columns
    - normalizing headers
    - converting indices/columns to MultiIndex form
    - adding MetaFrames rows unique identifiers

    Parameters
    ----------
    df: 'DataFrame'

    Returns
    -------
    DataFrame
        A modified copy of the original DataFrame ready for export.

    Notes
    -----
    The original DataFrame is not modified.
    """
    df = df.copy()
    if self.is_table:
        if self.opts.index:
            if df.index.name in [None, 0]:
                # For reading to work corrrectly when index = True and header = True
                df.index.name = DF_EMPTY_CELL
        return df
    if not self.opts.index:
        df = df.reset_index(drop=True)
        df.index.name = DF_EMPTY_CELL
    if not self.opts.header:
        df.columns = range(df.shape[1])
        # df.columns.name = DF_EMPTY_CELL
    if not is_mi(df.index):
        if df.index.name in [0, '0', '', None]:
            df.index.name = DF_EMPTY_CELL
        df.index = pd.MultiIndex.from_frame(df.mfr)
        df.index.names = [DF_EMPTY_CELL]
    if not is_mi(df.columns):
        if df.columns.name in [0, '0', '', None]:
            df.columns.name = DF_EMPTY_CELL
        df.columns = pd.MultiIndex.from_frame(df.mfc)
    if self.opts.extensive:
        # Add unique IDs to MFR and MFC
        mfr = df.mf(axis=0)
        mfr.insert(0, COLNAME_METAFRAME_UNIQUE_ID, df.mfr.index+1)
        df.mfr = mfr
        mfc = df.mf(axis=1)
        mfc.insert(0, COLNAME_METAFRAME_UNIQUE_ID, df.mfc.index+1)
        df.mfc = mfc
    return df