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