1from __future__ import annotations
2
3from typing import (
4 TYPE_CHECKING,
5 Any,
6 ClassVar,
7)
8
9import numpy as np
10
11from pandas.util._decorators import set_module
12
13from pandas.core.dtypes.base import register_extension_dtype
14from pandas.core.dtypes.common import is_float_dtype
15
16from pandas.core.arrays.numeric import (
17 NumericArray,
18 NumericDtype,
19)
20
21if TYPE_CHECKING:
22 from collections.abc import Callable
23
24
25class FloatingDtype(NumericDtype):
26 """
27 An ExtensionDtype to hold a single size of floating dtype.
28
29 These specific implementations are subclasses of the non-public
30 FloatingDtype. For example we have Float32Dtype to represent float32.
31
32 The attributes name & type are set when these subclasses are created.
33 """
34
35 # The value used to fill '_data' to avoid upcasting
36 _internal_fill_value = np.nan
37 _default_np_dtype = np.dtype(np.float64)
38 _checker: Callable[[Any], bool] = is_float_dtype
39
40 def construct_array_type(self) -> type[FloatingArray]:
41 """
42 Return the array type associated with this dtype.
43
44 Returns
45 -------
46 type
47 """
48 return FloatingArray
49
50 @classmethod
51 def _get_dtype_mapping(cls) -> dict[np.dtype, FloatingDtype]:
52 return NUMPY_FLOAT_TO_DTYPE
53
54 @classmethod
55 def _safe_cast(cls, values: np.ndarray, dtype: np.dtype, copy: bool) -> np.ndarray:
56 """
57 Safely cast the values to the given dtype.
58
59 "safe" in this context means the casting is lossless.
60 """
61 # This is really only here for compatibility with IntegerDtype
62 # Here for compat with IntegerDtype
63 return values.astype(dtype, copy=copy)
64
65
66@set_module("pandas.arrays")
67class FloatingArray(NumericArray):
68 """
69 Array of floating (optional missing) values.
70
71 .. warning::
72
73 FloatingArray is currently experimental, and its API or internal
74 implementation may change without warning. Especially the behaviour
75 regarding NaN (distinct from NA missing values) is subject to change.
76
77 We represent a FloatingArray with 2 numpy arrays:
78
79 - data: contains a numpy float array of the appropriate dtype
80 - mask: a boolean array holding a mask on the data, True is missing
81
82 To construct a FloatingArray from generic array-like input, use
83 :func:`pandas.array` with one of the float dtypes (see examples).
84
85 See :ref:`integer_na` for more.
86
87 Parameters
88 ----------
89 values : numpy.ndarray
90 A 1-d float-dtype array.
91 mask : numpy.ndarray
92 A 1-d boolean-dtype array indicating missing values.
93 copy : bool, default False
94 Whether to copy the `values` and `mask`.
95
96 Attributes
97 ----------
98 None
99
100 Methods
101 -------
102 None
103
104 Returns
105 -------
106 FloatingArray
107
108 See Also
109 --------
110 array : Create an array.
111 Float32Dtype : Float32 dtype for FloatingArray.
112 Float64Dtype : Float64 dtype for FloatingArray.
113 Series : One-dimensional labeled array capable of holding data.
114 DataFrame : Two-dimensional, size-mutable, potentially heterogeneous tabular data.
115
116 Examples
117 --------
118 Create a FloatingArray with :func:`pandas.array`:
119
120 >>> pd.array([0.1, None, 0.3], dtype=pd.Float32Dtype())
121 <FloatingArray>
122 [0.1, <NA>, 0.3]
123 Length: 3, dtype: Float32
124
125 String aliases for the dtypes are also available. They are capitalized.
126
127 >>> pd.array([0.1, None, 0.3], dtype="Float32")
128 <FloatingArray>
129 [0.1, <NA>, 0.3]
130 Length: 3, dtype: Float32
131 """
132
133 _dtype_cls = FloatingDtype
134
135
136_dtype_docstring = """
137An ExtensionDtype for {dtype} data.
138
139This dtype uses ``pd.NA`` as missing value indicator.
140
141Attributes
142----------
143None
144
145Methods
146-------
147None
148
149See Also
150--------
151CategoricalDtype : Type for categorical data with the categories and orderedness.
152IntegerDtype : An ExtensionDtype to hold a single size & kind of integer dtype.
153StringDtype : An ExtensionDtype for string data.
154
155Examples
156--------
157For Float32Dtype:
158
159>>> ser = pd.Series([2.25, pd.NA], dtype=pd.Float32Dtype())
160>>> ser.dtype
161Float32Dtype()
162
163For Float64Dtype:
164
165>>> ser = pd.Series([2.25, pd.NA], dtype=pd.Float64Dtype())
166>>> ser.dtype
167Float64Dtype()
168"""
169
170# create the Dtype
171
172
173@register_extension_dtype
174@set_module("pandas")
175class Float32Dtype(FloatingDtype):
176 type = np.float32
177 name: ClassVar[str] = "Float32"
178 __doc__ = _dtype_docstring.format(dtype="float32")
179
180
181@register_extension_dtype
182@set_module("pandas")
183class Float64Dtype(FloatingDtype):
184 type = np.float64
185 name: ClassVar[str] = "Float64"
186 __doc__ = _dtype_docstring.format(dtype="float64")
187
188
189NUMPY_FLOAT_TO_DTYPE: dict[np.dtype, FloatingDtype] = {
190 np.dtype(np.float32): Float32Dtype(),
191 np.dtype(np.float64): Float64Dtype(),
192}