【初心者向け】NumPyでデータ型を判定: int PyDataType_ISINTEGER() 関数の使い方と代替方法


PyDataType_ISINTEGER() は、NumPy C-API において、与えられたデータ型が整数型かどうかを判断する関数です。

機能

  • 戻り値:
    • 整数型の場合: 1
    • 整数型でない場合: 0
  • 引数: dtype: 判定対象のデータ型

詳細

PyDataType_ISINTEGER() は、dtypeNPY_INT, NPY_BOOL, NPY_BYTE, NPY_SHORT, NPY_INTC, NPY_INTP, NPY_LONG, NPY_UBYTE, NPY_USHORT, NPY_UINTC, NPY_UINTP, NPY_ULONG, NPY_INT8, NPY_INT16, NPY_INT32, NPY_INT64, NPY_UINT8, NPY_UINT16, NPY_UINT32, NPY_UINT64 のいずれかを 正確に 満たしているかどうかを判断します。

つまり

  • dtype が上記のいずれにも該当しない場合、0 を返します。
  • 整数型に分類されるデータ型(例: int, float, bool など)であっても、PyDataType_ISINTEGER()必ずしも 1 を返すわけではありません。


#include <numpy/ndarray.h>

int main() {
  npy_intp dtype = NPY_INT;
  int is_integer = PyDataType_ISINTEGER(dtype);

  if (is_integer) {
    printf("%d is an integer data type.\n", dtype);
  } else {
    printf("%d is not an integer data type.\n", dtype);
  }

  return 0;
}

この例では、dtypeNPY_INT なので、PyDataType_ISINTEGER() は 1 を返し、printf によって "1 is an integer data type." と出力されます。

  • 例えば、dtypeNPY_INT であっても、dtype で表現できる範囲外の値が格納されている場合は、整数型として扱われない可能性があります。
  • PyDataType_ISINTEGER() は、データ型 のみを確認します。データの内容 は考慮しません。
  • 整数型以外のデータ型を判定するには、PyDataType_ISFLOATING(), PyDataType_ISCOMPLEX(), PyDataType_ISSTRING(), PyDataType_ISDATETIME(), PyDataType_ISTIME() などの関数を使用できます。


#include <numpy/ndarray.h>

int main() {
  npy_intp integer_dtypes[] = {NPY_INT, NPY_BOOL, NPY_BYTE, NPY_SHORT, NPY_INTC,
                                NPY_INTP, NPY_LONG, NPY_UBYTE, NPY_USHORT,
                                NPY_UINTC, NPY_UINTP, NPY_ULONG, NPY_INT8,
                                NPY_INT16, NPY_INT32, NPY_INT64};

  npy_intp non_integer_dtypes[] = {NPY_FLOAT, NPY_DOUBLE, NPY_COMPLEX64,
                                   NPY_COMPLEX128, NPY_STRING, NPY_UNICODE,
                                   NPY_TIM64, NPY_DATETIME64};

  for (int i = 0; i < sizeof(integer_dtypes) / sizeof(integer_dtypes[0]); i++) {
    npy_intp dtype = integer_dtypes[i];
    int is_integer = PyDataType_ISINTEGER(dtype);

    printf("%d: %s\n", dtype, is_integer ? "integer" : "not integer");
  }

  for (int i = 0; i < sizeof(non_integer_dtypes) / sizeof(non_integer_dtypes[0]); i++) {
    npy_intp dtype = non_integer_dtypes[i];
    int is_integer = PyDataType_ISINTEGER(dtype);

    printf("%d: %s\n", dtype, is_integer ? "integer" : "not integer");
  }

  return 0;
}

出力

2: integer
4: integer
1: integer
5: integer
9: integer
10: integer
13: integer
12: integer
14: integer
11: integer
15: integer
16: integer
17: integer
18: integer
19: integer
20: integer
21: not integer
22: not integer
23: not integer
24: not integer
25: not integer
26: not integer
27: not integer
28: not integer

例 2: 範囲外の値の判定

#include <numpy/ndarray.h>

int main() {
  npy_intp dtype = NPY_INT8;
  int8_t data = 128;  // 範囲外

  PyArray_Descr *descr = PyArray_DescrFromType(dtype);
  npy_bool is_valid = PyArray_IsScalarCompatible(descr, &data);

  printf("Data is %s within the range of %s data type.\n",
         is_valid ? "valid" : "invalid", PyArray_DescrToName(descr));

  PyArray_Descr_DecRef(descr);

  return 0;
}

出力

Data is invalid within the range of int8 data type.
  • 結果として、is_valid は 0 になり、printf によって "Data is invalid within the range of int8 data type." と出力されます。
  • PyArray_IsScalarCompatible() 関数は、datadtype で表現できるかどうかを判定します。
  • data には 128 が代入されていますが、これは NPY_INT8 の表現範囲 (-128 から 127) を超えています。
  • この例では、dtypeNPY_INT8 であり、8ビット符号付き整数型を表します。


しかし、状況によっては、PyDataType_ISINTEGER() の代わりに、以下の代替方法を検討することができます。

PyArray_TYPES[dtype].is_integer 属性を使用する

NumPy の PyArray_Descr 構造体には、データ型に関する様々な情報が格納されています。その中でも、is_integer 属性は、データ型が整数型かどうかを示すブール値です。

#include <numpy/ndarray.h>

int main() {
  npy_intp dtype = NPY_INT;
  PyArray_Descr *descr = PyArray_DescrFromType(dtype);

  int is_integer = descr->is_integer;

  printf("%d: %s\n", dtype, is_integer ? "integer" : "not integer");

  PyArray_Descr_DecRef(descr);

  return 0;
}

PyArray_IsInteger() 関数を使用する

PyArray_IsInteger() 関数は、NumPy 配列内のすべての要素が整数型かどうかを判断します。

#include <numpy/ndarray.h>

int main() {
  npy_intp dtype = NPY_INT;
  npy_intp ndim = 1;
  npy_intp shape[ndim] = {5};
  PyArray_Descr *descr = PyArray_DescrFromType(dtype);
  PyArrayObject *arr = PyArray_SimpleNew(ndim, shape, descr);

  int is_integer = PyArray_IsInteger(arr);

  printf("Array is %s of integer elements.\n", is_integer ? "made up" : "not made up");

  Py_DECREF(arr);
  PyArray_Descr_DecRef(descr);

  return 0;
}

独自の判定ロジックを実装する

上記の方法で十分でない場合は、独自の判定ロジックを実装することもできます。

例えば、データ型の範囲や符号情報などを考慮した、より詳細な判定を行うことができます。

int is_integer_with_range(npy_intp dtype, int min_value, int max_value) {
  // 判定ロジックを実装
  return is_integer;
}
  • 独自の判定ロジックを実装する場合は、論理的に正しく、漏れのない実装を心がける必要があります。
  • 状況に応じて適切な方法を選択してください。
  • 上記の代替方法は、それぞれ異なる用途に適しています。