Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
pola-rs
GitHub Repository: pola-rs/polars
Path: blob/main/crates/polars-core/src/series/ops/downcast.rs
6940 views
1
#![allow(unsafe_op_in_unsafe_fn)]
2
use crate::prelude::*;
3
use crate::series::implementations::null::NullChunked;
4
5
macro_rules! unpack_chunked_err {
6
($series:expr => $name:expr) => {
7
polars_err!(SchemaMismatch: "invalid series dtype: expected `{}`, got `{}` for series with name `{}`", $name, $series.dtype(), $series.name())
8
};
9
}
10
11
macro_rules! try_unpack_chunked {
12
($series:expr, $expected:pat $(if $guard: expr)? => $ca:ty) => {
13
match $series.dtype() {
14
$expected $(if $guard)? => {
15
// Check downcast in debug compiles
16
#[cfg(debug_assertions)]
17
{
18
Some($series.as_ref().as_any().downcast_ref::<$ca>().unwrap())
19
}
20
#[cfg(not(debug_assertions))]
21
unsafe {
22
Some(&*($series.as_ref() as *const dyn SeriesTrait as *const $ca))
23
}
24
},
25
_ => None,
26
}
27
};
28
}
29
30
impl Series {
31
/// Unpack to [`ChunkedArray`] of dtype [`DataType::Int8`]
32
pub fn try_i8(&self) -> Option<&Int8Chunked> {
33
try_unpack_chunked!(self, DataType::Int8 => Int8Chunked)
34
}
35
36
/// Unpack to [`ChunkedArray`] of dtype [`DataType::Int16`]
37
pub fn try_i16(&self) -> Option<&Int16Chunked> {
38
try_unpack_chunked!(self, DataType::Int16 => Int16Chunked)
39
}
40
41
/// Unpack to [`ChunkedArray`]
42
/// ```
43
/// # use polars_core::prelude::*;
44
/// let s = Series::new("foo".into(), [1i32 ,2, 3]);
45
/// let s_squared: Series = s.i32()
46
/// .unwrap()
47
/// .into_iter()
48
/// .map(|opt_v| {
49
/// match opt_v {
50
/// Some(v) => Some(v * v),
51
/// None => None, // null value
52
/// }
53
/// }).collect();
54
/// ```
55
/// Unpack to [`ChunkedArray`] of dtype [`DataType::Int32`]
56
pub fn try_i32(&self) -> Option<&Int32Chunked> {
57
try_unpack_chunked!(self, DataType::Int32 => Int32Chunked)
58
}
59
60
/// Unpack to [`ChunkedArray`] of dtype [`DataType::Int64`]
61
pub fn try_i64(&self) -> Option<&Int64Chunked> {
62
try_unpack_chunked!(self, DataType::Int64 => Int64Chunked)
63
}
64
65
/// Unpack to [`ChunkedArray`] of dtype [`DataType::Int128`]
66
#[cfg(feature = "dtype-i128")]
67
pub fn try_i128(&self) -> Option<&Int128Chunked> {
68
try_unpack_chunked!(self, DataType::Int128 => Int128Chunked)
69
}
70
71
/// Unpack to [`ChunkedArray`] of dtype [`DataType::Float32`]
72
pub fn try_f32(&self) -> Option<&Float32Chunked> {
73
try_unpack_chunked!(self, DataType::Float32 => Float32Chunked)
74
}
75
76
/// Unpack to [`ChunkedArray`] of dtype [`DataType::Float64`]
77
pub fn try_f64(&self) -> Option<&Float64Chunked> {
78
try_unpack_chunked!(self, DataType::Float64 => Float64Chunked)
79
}
80
81
/// Unpack to [`ChunkedArray`] of dtype [`DataType::UInt8`]
82
pub fn try_u8(&self) -> Option<&UInt8Chunked> {
83
try_unpack_chunked!(self, DataType::UInt8 => UInt8Chunked)
84
}
85
86
/// Unpack to [`ChunkedArray`] of dtype [`DataType::UInt16`]
87
pub fn try_u16(&self) -> Option<&UInt16Chunked> {
88
try_unpack_chunked!(self, DataType::UInt16 => UInt16Chunked)
89
}
90
91
/// Unpack to [`ChunkedArray`] of dtype [`DataType::UInt32`]
92
pub fn try_u32(&self) -> Option<&UInt32Chunked> {
93
try_unpack_chunked!(self, DataType::UInt32 => UInt32Chunked)
94
}
95
96
/// Unpack to [`ChunkedArray`] of dtype [`DataType::UInt64`]
97
pub fn try_u64(&self) -> Option<&UInt64Chunked> {
98
try_unpack_chunked!(self, DataType::UInt64 => UInt64Chunked)
99
}
100
101
/// Unpack to [`ChunkedArray`] of dtype [`DataType::Boolean`]
102
pub fn try_bool(&self) -> Option<&BooleanChunked> {
103
try_unpack_chunked!(self, DataType::Boolean => BooleanChunked)
104
}
105
106
/// Unpack to [`ChunkedArray`] of dtype [`DataType::String`]
107
pub fn try_str(&self) -> Option<&StringChunked> {
108
try_unpack_chunked!(self, DataType::String => StringChunked)
109
}
110
111
/// Unpack to [`ChunkedArray`] of dtype [`DataType::Binary`]
112
pub fn try_binary(&self) -> Option<&BinaryChunked> {
113
try_unpack_chunked!(self, DataType::Binary => BinaryChunked)
114
}
115
116
/// Unpack to [`ChunkedArray`] of dtype [`DataType::Binary`]
117
pub fn try_binary_offset(&self) -> Option<&BinaryOffsetChunked> {
118
try_unpack_chunked!(self, DataType::BinaryOffset => BinaryOffsetChunked)
119
}
120
121
/// Unpack to [`ChunkedArray`] of dtype [`DataType::Time`]
122
#[cfg(feature = "dtype-time")]
123
pub fn try_time(&self) -> Option<&TimeChunked> {
124
try_unpack_chunked!(self, DataType::Time => TimeChunked)
125
}
126
127
/// Unpack to [`ChunkedArray`] of dtype [`DataType::Date`]
128
#[cfg(feature = "dtype-date")]
129
pub fn try_date(&self) -> Option<&DateChunked> {
130
try_unpack_chunked!(self, DataType::Date => DateChunked)
131
}
132
133
/// Unpack to [`ChunkedArray`] of dtype [`DataType::Datetime`]
134
#[cfg(feature = "dtype-datetime")]
135
pub fn try_datetime(&self) -> Option<&DatetimeChunked> {
136
try_unpack_chunked!(self, DataType::Datetime(_, _) => DatetimeChunked)
137
}
138
139
/// Unpack to [`ChunkedArray`] of dtype [`DataType::Duration`]
140
#[cfg(feature = "dtype-duration")]
141
pub fn try_duration(&self) -> Option<&DurationChunked> {
142
try_unpack_chunked!(self, DataType::Duration(_) => DurationChunked)
143
}
144
145
/// Unpack to [`ChunkedArray`] of dtype [`DataType::Decimal`]
146
#[cfg(feature = "dtype-decimal")]
147
pub fn try_decimal(&self) -> Option<&DecimalChunked> {
148
try_unpack_chunked!(self, DataType::Decimal(_, _) => DecimalChunked)
149
}
150
151
/// Unpack to [`ChunkedArray`] of dtype list
152
pub fn try_list(&self) -> Option<&ListChunked> {
153
try_unpack_chunked!(self, DataType::List(_) => ListChunked)
154
}
155
156
/// Unpack to [`ChunkedArray`] of dtype [`DataType::Array`]
157
#[cfg(feature = "dtype-array")]
158
pub fn try_array(&self) -> Option<&ArrayChunked> {
159
try_unpack_chunked!(self, DataType::Array(_, _) => ArrayChunked)
160
}
161
162
#[cfg(feature = "dtype-categorical")]
163
pub fn try_cat<T: PolarsCategoricalType>(&self) -> Option<&CategoricalChunked<T>> {
164
try_unpack_chunked!(self, dt @ DataType::Enum(_, _) | dt @ DataType::Categorical(_, _) if dt.cat_physical().unwrap() == T::physical() => CategoricalChunked<T>)
165
}
166
167
/// Unpack to [`ChunkedArray`] of dtype [`DataType::Categorical`] or [`DataType::Enum`] with a physical type of UInt8.
168
#[cfg(feature = "dtype-categorical")]
169
pub fn try_cat8(&self) -> Option<&Categorical8Chunked> {
170
self.try_cat::<Categorical8Type>()
171
}
172
173
#[cfg(feature = "dtype-categorical")]
174
pub fn try_cat16(&self) -> Option<&Categorical16Chunked> {
175
self.try_cat::<Categorical16Type>()
176
}
177
178
#[cfg(feature = "dtype-categorical")]
179
pub fn try_cat32(&self) -> Option<&Categorical32Chunked> {
180
self.try_cat::<Categorical32Type>()
181
}
182
183
/// Unpack to [`ChunkedArray`] of dtype [`DataType::Struct`]
184
#[cfg(feature = "dtype-struct")]
185
pub fn try_struct(&self) -> Option<&StructChunked> {
186
#[cfg(debug_assertions)]
187
{
188
if let DataType::Struct(_) = self.dtype() {
189
let any = self.as_any();
190
assert!(any.is::<StructChunked>());
191
}
192
}
193
try_unpack_chunked!(self, DataType::Struct(_) => StructChunked)
194
}
195
196
/// Unpack to [`ChunkedArray`] of dtype [`DataType::Null`]
197
pub fn try_null(&self) -> Option<&NullChunked> {
198
try_unpack_chunked!(self, DataType::Null => NullChunked)
199
}
200
/// Unpack to [`ChunkedArray`] of dtype [`DataType::Int8`]
201
pub fn i8(&self) -> PolarsResult<&Int8Chunked> {
202
self.try_i8()
203
.ok_or_else(|| unpack_chunked_err!(self => "Int8"))
204
}
205
206
/// Unpack to [`ChunkedArray`] of dtype [`DataType::Int16`]
207
pub fn i16(&self) -> PolarsResult<&Int16Chunked> {
208
self.try_i16()
209
.ok_or_else(|| unpack_chunked_err!(self => "Int16"))
210
}
211
212
/// Unpack to [`ChunkedArray`]
213
/// ```
214
/// # use polars_core::prelude::*;
215
/// let s = Series::new("foo".into(), [1i32 ,2, 3]);
216
/// let s_squared: Series = s.i32()
217
/// .unwrap()
218
/// .into_iter()
219
/// .map(|opt_v| {
220
/// match opt_v {
221
/// Some(v) => Some(v * v),
222
/// None => None, // null value
223
/// }
224
/// }).collect();
225
/// ```
226
/// Unpack to [`ChunkedArray`] of dtype [`DataType::Int32`]
227
pub fn i32(&self) -> PolarsResult<&Int32Chunked> {
228
self.try_i32()
229
.ok_or_else(|| unpack_chunked_err!(self => "Int32"))
230
}
231
232
/// Unpack to [`ChunkedArray`] of dtype [`DataType::Int64`]
233
pub fn i64(&self) -> PolarsResult<&Int64Chunked> {
234
self.try_i64()
235
.ok_or_else(|| unpack_chunked_err!(self => "Int64"))
236
}
237
238
/// Unpack to [`ChunkedArray`] of dtype [`DataType::Int128`]
239
#[cfg(feature = "dtype-i128")]
240
pub fn i128(&self) -> PolarsResult<&Int128Chunked> {
241
self.try_i128()
242
.ok_or_else(|| unpack_chunked_err!(self => "Int128"))
243
}
244
245
/// Unpack to [`ChunkedArray`] of dtype [`DataType::Float32`]
246
pub fn f32(&self) -> PolarsResult<&Float32Chunked> {
247
self.try_f32()
248
.ok_or_else(|| unpack_chunked_err!(self => "Float32"))
249
}
250
251
/// Unpack to [`ChunkedArray`] of dtype [`DataType::Float64`]
252
pub fn f64(&self) -> PolarsResult<&Float64Chunked> {
253
self.try_f64()
254
.ok_or_else(|| unpack_chunked_err!(self => "Float64"))
255
}
256
257
/// Unpack to [`ChunkedArray`] of dtype [`DataType::UInt8`]
258
pub fn u8(&self) -> PolarsResult<&UInt8Chunked> {
259
self.try_u8()
260
.ok_or_else(|| unpack_chunked_err!(self => "UInt8"))
261
}
262
263
/// Unpack to [`ChunkedArray`] of dtype [`DataType::UInt16`]
264
pub fn u16(&self) -> PolarsResult<&UInt16Chunked> {
265
self.try_u16()
266
.ok_or_else(|| unpack_chunked_err!(self => "UInt16"))
267
}
268
269
/// Unpack to [`ChunkedArray`] of dtype [`DataType::UInt32`]
270
pub fn u32(&self) -> PolarsResult<&UInt32Chunked> {
271
self.try_u32()
272
.ok_or_else(|| unpack_chunked_err!(self => "UInt32"))
273
}
274
275
/// Unpack to [`ChunkedArray`] of dtype [`DataType::UInt64`]
276
pub fn u64(&self) -> PolarsResult<&UInt64Chunked> {
277
self.try_u64()
278
.ok_or_else(|| unpack_chunked_err!(self => "UInt64"))
279
}
280
281
/// Unpack to [`ChunkedArray`] of dtype [`DataType::Boolean`]
282
pub fn bool(&self) -> PolarsResult<&BooleanChunked> {
283
self.try_bool()
284
.ok_or_else(|| unpack_chunked_err!(self => "Boolean"))
285
}
286
287
/// Unpack to [`ChunkedArray`] of dtype [`DataType::String`]
288
pub fn str(&self) -> PolarsResult<&StringChunked> {
289
self.try_str()
290
.ok_or_else(|| unpack_chunked_err!(self => "String"))
291
}
292
293
/// Unpack to [`ChunkedArray`] of dtype [`DataType::Binary`]
294
pub fn binary(&self) -> PolarsResult<&BinaryChunked> {
295
self.try_binary()
296
.ok_or_else(|| unpack_chunked_err!(self => "Binary"))
297
}
298
299
/// Unpack to [`ChunkedArray`] of dtype [`DataType::Binary`]
300
pub fn binary_offset(&self) -> PolarsResult<&BinaryOffsetChunked> {
301
self.try_binary_offset()
302
.ok_or_else(|| unpack_chunked_err!(self => "BinaryOffset"))
303
}
304
305
/// Unpack to [`ChunkedArray`] of dtype [`DataType::Time`]
306
#[cfg(feature = "dtype-time")]
307
pub fn time(&self) -> PolarsResult<&TimeChunked> {
308
self.try_time()
309
.ok_or_else(|| unpack_chunked_err!(self => "Time"))
310
}
311
312
/// Unpack to [`ChunkedArray`] of dtype [`DataType::Date`]
313
#[cfg(feature = "dtype-date")]
314
pub fn date(&self) -> PolarsResult<&DateChunked> {
315
self.try_date()
316
.ok_or_else(|| unpack_chunked_err!(self => "Date"))
317
}
318
319
/// Unpack to [`ChunkedArray`] of dtype [`DataType::Datetime`]
320
#[cfg(feature = "dtype-datetime")]
321
pub fn datetime(&self) -> PolarsResult<&DatetimeChunked> {
322
self.try_datetime()
323
.ok_or_else(|| unpack_chunked_err!(self => "Datetime"))
324
}
325
326
/// Unpack to [`ChunkedArray`] of dtype [`DataType::Duration`]
327
#[cfg(feature = "dtype-duration")]
328
pub fn duration(&self) -> PolarsResult<&DurationChunked> {
329
self.try_duration()
330
.ok_or_else(|| unpack_chunked_err!(self => "Duration"))
331
}
332
333
/// Unpack to [`ChunkedArray`] of dtype [`DataType::Decimal`]
334
#[cfg(feature = "dtype-decimal")]
335
pub fn decimal(&self) -> PolarsResult<&DecimalChunked> {
336
self.try_decimal()
337
.ok_or_else(|| unpack_chunked_err!(self => "Decimal"))
338
}
339
340
/// Unpack to [`ChunkedArray`] of dtype list
341
pub fn list(&self) -> PolarsResult<&ListChunked> {
342
self.try_list()
343
.ok_or_else(|| unpack_chunked_err!(self => "List"))
344
}
345
346
/// Unpack to [`ChunkedArray`] of dtype [`DataType::Array`]
347
#[cfg(feature = "dtype-array")]
348
pub fn array(&self) -> PolarsResult<&ArrayChunked> {
349
self.try_array()
350
.ok_or_else(|| unpack_chunked_err!(self => "Array"))
351
}
352
353
/// Unpack to [`ChunkedArray`] of dtype [`DataType::Categorical`] or [`DataType::Enum`].
354
#[cfg(feature = "dtype-categorical")]
355
pub fn cat<T: PolarsCategoricalType>(&self) -> PolarsResult<&CategoricalChunked<T>> {
356
self.try_cat::<T>()
357
.ok_or_else(|| unpack_chunked_err!(self => "Enum | Categorical"))
358
}
359
360
/// Unpack to [`ChunkedArray`] of dtype [`DataType::Categorical`] or [`DataType::Enum`] with a physical type of UInt8.
361
#[cfg(feature = "dtype-categorical")]
362
pub fn cat8(&self) -> PolarsResult<&CategoricalChunked<Categorical8Type>> {
363
self.try_cat8()
364
.ok_or_else(|| unpack_chunked_err!(self => "Enum8 | Categorical8"))
365
}
366
367
/// Unpack to [`ChunkedArray`] of dtype [`DataType::Categorical`] or [`DataType::Enum`] with a physical type of UInt16.
368
#[cfg(feature = "dtype-categorical")]
369
pub fn cat16(&self) -> PolarsResult<&CategoricalChunked<Categorical16Type>> {
370
self.try_cat16()
371
.ok_or_else(|| unpack_chunked_err!(self => "Enum16 | Categorical16"))
372
}
373
374
/// Unpack to [`ChunkedArray`] of dtype [`DataType::Categorical`] or [`DataType::Enum`] with a physical type of UInt32.
375
#[cfg(feature = "dtype-categorical")]
376
pub fn cat32(&self) -> PolarsResult<&CategoricalChunked<Categorical32Type>> {
377
self.try_cat32()
378
.ok_or_else(|| unpack_chunked_err!(self => "Enum32 | Categorical32"))
379
}
380
381
/// Unpack to [`ChunkedArray`] of dtype [`DataType::Struct`]
382
#[cfg(feature = "dtype-struct")]
383
pub fn struct_(&self) -> PolarsResult<&StructChunked> {
384
#[cfg(debug_assertions)]
385
{
386
if let DataType::Struct(_) = self.dtype() {
387
let any = self.as_any();
388
assert!(any.is::<StructChunked>());
389
}
390
}
391
392
self.try_struct()
393
.ok_or_else(|| unpack_chunked_err!(self => "Struct"))
394
}
395
396
/// Unpack to [`ChunkedArray`] of dtype [`DataType::Null`]
397
pub fn null(&self) -> PolarsResult<&NullChunked> {
398
self.try_null()
399
.ok_or_else(|| unpack_chunked_err!(self => "Null"))
400
}
401
}
402
403