開発者#

このセクションでは、pandasの下流アプリケーションに焦点を当てます。

Apache Parquet形式でのpandas DataFrameオブジェクトの保存#

Apache Parquet形式は、ファイルと列レベルでキーバリューメタデータを提供し、Parquetファイルのフッターに保存されます。

5: optional list<KeyValue> key_value_metadata

ここでKeyValue

struct KeyValue {
  1: required string key
  2: optional string value
}

pandas.DataFrameを忠実に再構築できるように、FileMetaDatapandasメタデータキーを、値を以下のように保存します。

{'index_columns': [<descr0>, <descr1>, ...],
 'column_indexes': [<ci0>, <ci1>, ..., <ciN>],
 'columns': [<c0>, <c1>, ...],
 'pandas_version': $VERSION,
 'creator': {
   'library': $LIBRARY,
   'version': $LIBRARY_VERSION
 }}

'index_columns'フィールド内の「記述子」値<descr0>は、文字列(列を参照)または以下に説明する値を持つ辞書です。

<c0>/<ci0>などは、各列(インデックス列を含む)のメタデータを含む辞書です。これはJSON形式です。

{'name': column_name,
 'field_name': parquet_column_name,
 'pandas_type': pandas_type,
 'numpy_type': numpy_type,
 'metadata': metadata}

詳細な仕様については、以下を参照してください。

インデックスメタデータ記述子#

RangeIndexは、シリアライズを必要とせず、メタデータのみとして保存できます。これらの記述子形式は以下のとおりです。

index = pd.RangeIndex(0, 10, 2)
{
    "kind": "range",
    "name": index.name,
    "start": index.start,
    "stop": index.stop,
    "step": index.step,
}

他のインデックスタイプは、他のDataFrame列と共にデータ列としてシリアライズする必要があります。これらのメタデータは、データ列内のフィールド名を指定する文字列です(例:'__index_level_0__')。

インデックスに非Noneのname属性があり、その値と一致する名前を持つ他の列がない場合、index.name値を記述子として使用できます。それ以外の場合は(名前のないインデックスと、他の列名と名前が衝突するインデックスの場合)、__index_level_\d+__に一致するパターンを持つあいまいさを解消する名前を使用する必要があります。データ列としての名前付きインデックスの場合、name属性は常に上記の列記述子に保存されます。

列メタデータ#

pandas_typeは列の論理タイプであり、次のいずれかです。

  • ブール値:'bool'

  • 整数:'int8', 'int16', 'int32', 'int64', 'uint8', 'uint16', 'uint32', 'uint64'

  • 浮動小数点数:'float16', 'float32', 'float64'

  • 日付と時刻の型:'datetime', 'datetimetz''timedelta'

  • 文字列:'unicode', 'bytes'

  • カテゴリカル:'categorical'

  • その他のPythonオブジェクト:'object'

numpy_typeは列の物理的なストレージタイプであり、データを保持する基になるNumPy配列のstr(dtype)の結果です。datetimetzの場合、これはdatetime64[ns]であり、カテゴリカルの場合、サポートされている整数カテゴリカルタイプのいずれかになります。

metadataフィールドは、次の場合を除いてNoneです。

  • datetimetz{'timezone': zone, 'unit': 'ns'}、例:{'timezone', 'America/New_York', 'unit': 'ns'}'unit'はオプションであり、省略された場合はナノ秒とみなされます。

  • categorical{'num_categories': K, 'ordered': is_ordered, 'type': $TYPE}

    • ここで'type'はオプションであり、ここで入れ子になったpandasタイプの仕様にすることができます(ただし、カテゴリカルではありません)。

  • unicode{'encoding': encoding}

    • エンコーディングはオプションであり、存在しない場合はUTF-8です。

  • object{'encoding': encoding}。オブジェクトはシリアライズしてBYTE_ARRAYParquet列に保存できます。エンコーディングは次のいずれかです。

    • 'pickle'

    • 'bson'

    • 'json'

  • timedelta{'unit': 'ns'}'unit'はオプションであり、省略された場合はナノ秒とみなされます。このメタデータは完全にオプションです。

これらのタイプ以外のタイプの場合、'metadata'キーは省略できます。実装では、キーが存在しない場合はNoneと想定できます。

完全に形成されたメタデータの例として

{'index_columns': ['__index_level_0__'],
 'column_indexes': [
     {'name': None,
      'field_name': 'None',
      'pandas_type': 'unicode',
      'numpy_type': 'object',
      'metadata': {'encoding': 'UTF-8'}}
 ],
 'columns': [
     {'name': 'c0',
      'field_name': 'c0',
      'pandas_type': 'int8',
      'numpy_type': 'int8',
      'metadata': None},
     {'name': 'c1',
      'field_name': 'c1',
      'pandas_type': 'bytes',
      'numpy_type': 'object',
      'metadata': None},
     {'name': 'c2',
      'field_name': 'c2',
      'pandas_type': 'categorical',
      'numpy_type': 'int16',
      'metadata': {'num_categories': 1000, 'ordered': False}},
     {'name': 'c3',
      'field_name': 'c3',
      'pandas_type': 'datetimetz',
      'numpy_type': 'datetime64[ns]',
      'metadata': {'timezone': 'America/Los_Angeles'}},
     {'name': 'c4',
      'field_name': 'c4',
      'pandas_type': 'object',
      'numpy_type': 'object',
      'metadata': {'encoding': 'pickle'}},
     {'name': None,
      'field_name': '__index_level_0__',
      'pandas_type': 'int64',
      'numpy_type': 'int64',
      'metadata': None}
 ],
 'pandas_version': '1.4.0',
 'creator': {
   'library': 'pyarrow',
   'version': '0.13.0'
 }}