Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
pola-rs
GitHub Repository: pola-rs/polars
Path: blob/main/crates/polars-core/src/named_from.rs
8433 views
1
use std::borrow::Cow;
2
3
#[cfg(feature = "dtype-duration")]
4
use chrono::Duration as ChronoDuration;
5
#[cfg(feature = "dtype-date")]
6
use chrono::NaiveDate;
7
#[cfg(feature = "dtype-datetime")]
8
use chrono::NaiveDateTime;
9
#[cfg(feature = "dtype-time")]
10
use chrono::NaiveTime;
11
#[cfg(feature = "dtype-f16")]
12
use polars_utils::float16::pf16;
13
14
use crate::chunked_array::builder::get_list_builder;
15
use crate::prelude::*;
16
17
pub trait NamedFrom<T, Phantom: ?Sized> {
18
/// Initialize by name and values.
19
fn new(name: PlSmallStr, _: T) -> Self;
20
}
21
22
pub trait NamedFromOwned<T> {
23
/// Initialize by name and values.
24
fn from_vec(name: PlSmallStr, _: T) -> Self;
25
}
26
27
macro_rules! impl_named_from_owned {
28
($type:ty, $polars_type:ident) => {
29
impl NamedFromOwned<$type> for Series {
30
fn from_vec(name: PlSmallStr, v: $type) -> Self {
31
ChunkedArray::<$polars_type>::from_vec(name, v).into_series()
32
}
33
}
34
};
35
}
36
37
#[cfg(feature = "dtype-i8")]
38
impl_named_from_owned!(Vec<i8>, Int8Type);
39
#[cfg(feature = "dtype-i16")]
40
impl_named_from_owned!(Vec<i16>, Int16Type);
41
impl_named_from_owned!(Vec<i32>, Int32Type);
42
impl_named_from_owned!(Vec<i64>, Int64Type);
43
#[cfg(feature = "dtype-i128")]
44
impl_named_from_owned!(Vec<i128>, Int128Type);
45
#[cfg(feature = "dtype-u8")]
46
impl_named_from_owned!(Vec<u8>, UInt8Type);
47
#[cfg(feature = "dtype-u16")]
48
impl_named_from_owned!(Vec<u16>, UInt16Type);
49
impl_named_from_owned!(Vec<u32>, UInt32Type);
50
impl_named_from_owned!(Vec<u64>, UInt64Type);
51
#[cfg(feature = "dtype-u128")]
52
impl_named_from_owned!(Vec<u128>, UInt128Type);
53
#[cfg(feature = "dtype-f16")]
54
impl_named_from_owned!(Vec<pf16>, Float16Type);
55
impl_named_from_owned!(Vec<f32>, Float32Type);
56
impl_named_from_owned!(Vec<f64>, Float64Type);
57
58
macro_rules! impl_named_from {
59
($type:ty, $polars_type:ident, $method:ident) => {
60
impl<T: AsRef<$type>> NamedFrom<T, $type> for Series {
61
fn new(name: PlSmallStr, v: T) -> Self {
62
ChunkedArray::<$polars_type>::$method(name, v.as_ref()).into_series()
63
}
64
}
65
impl<T: AsRef<$type>> NamedFrom<T, $type> for ChunkedArray<$polars_type> {
66
fn new(name: PlSmallStr, v: T) -> Self {
67
ChunkedArray::<$polars_type>::$method(name, v.as_ref())
68
}
69
}
70
};
71
}
72
73
impl_named_from!([String], StringType, from_slice);
74
impl_named_from!([Vec<u8>], BinaryType, from_slice);
75
impl_named_from!([bool], BooleanType, from_slice);
76
#[cfg(feature = "dtype-u8")]
77
impl_named_from!([u8], UInt8Type, from_slice);
78
#[cfg(feature = "dtype-u16")]
79
impl_named_from!([u16], UInt16Type, from_slice);
80
impl_named_from!([u32], UInt32Type, from_slice);
81
impl_named_from!([u64], UInt64Type, from_slice);
82
#[cfg(feature = "dtype-u128")]
83
impl_named_from!([u128], UInt128Type, from_slice);
84
#[cfg(feature = "dtype-i8")]
85
impl_named_from!([i8], Int8Type, from_slice);
86
#[cfg(feature = "dtype-i16")]
87
impl_named_from!([i16], Int16Type, from_slice);
88
impl_named_from!([i32], Int32Type, from_slice);
89
impl_named_from!([i64], Int64Type, from_slice);
90
#[cfg(any(feature = "dtype-i128", feature = "dtype-decimal"))]
91
impl_named_from!([i128], Int128Type, from_slice);
92
#[cfg(feature = "dtype-f16")]
93
impl_named_from!([pf16], Float16Type, from_slice);
94
impl_named_from!([f32], Float32Type, from_slice);
95
impl_named_from!([f64], Float64Type, from_slice);
96
impl_named_from!([Option<String>], StringType, from_slice_options);
97
impl_named_from!([Option<Vec<u8>>], BinaryType, from_slice_options);
98
impl_named_from!([Option<bool>], BooleanType, from_slice_options);
99
#[cfg(feature = "dtype-u8")]
100
impl_named_from!([Option<u8>], UInt8Type, from_slice_options);
101
#[cfg(feature = "dtype-u16")]
102
impl_named_from!([Option<u16>], UInt16Type, from_slice_options);
103
impl_named_from!([Option<u32>], UInt32Type, from_slice_options);
104
impl_named_from!([Option<u64>], UInt64Type, from_slice_options);
105
#[cfg(feature = "dtype-u128")]
106
impl_named_from!([Option<u128>], UInt128Type, from_slice_options);
107
#[cfg(feature = "dtype-i8")]
108
impl_named_from!([Option<i8>], Int8Type, from_slice_options);
109
#[cfg(feature = "dtype-i16")]
110
impl_named_from!([Option<i16>], Int16Type, from_slice_options);
111
impl_named_from!([Option<i32>], Int32Type, from_slice_options);
112
impl_named_from!([Option<i64>], Int64Type, from_slice_options);
113
#[cfg(any(feature = "dtype-i128", feature = "dtype-decimal"))]
114
impl_named_from!([Option<i128>], Int128Type, from_slice_options);
115
#[cfg(feature = "dtype-f16")]
116
impl_named_from!([Option<pf16>], Float16Type, from_slice_options);
117
impl_named_from!([Option<f32>], Float32Type, from_slice_options);
118
impl_named_from!([Option<f64>], Float64Type, from_slice_options);
119
120
macro_rules! impl_named_from_range {
121
($range:ty, $polars_type:ident) => {
122
impl NamedFrom<$range, $polars_type> for ChunkedArray<$polars_type> {
123
fn new(name: PlSmallStr, range: $range) -> Self {
124
let values = range.collect::<Vec<_>>();
125
ChunkedArray::<$polars_type>::from_vec(name, values)
126
}
127
}
128
129
impl NamedFrom<$range, $polars_type> for Series {
130
fn new(name: PlSmallStr, range: $range) -> Self {
131
ChunkedArray::new(name, range).into_series()
132
}
133
}
134
};
135
}
136
impl_named_from_range!(std::ops::Range<i64>, Int64Type);
137
impl_named_from_range!(std::ops::Range<i32>, Int32Type);
138
impl_named_from_range!(std::ops::Range<u64>, UInt64Type);
139
impl_named_from_range!(std::ops::Range<u32>, UInt32Type);
140
141
impl<T: AsRef<[Series]>> NamedFrom<T, ListType> for Series {
142
fn new(name: PlSmallStr, s: T) -> Self {
143
let series_slice = s.as_ref();
144
let list_cap = series_slice.len();
145
146
if series_slice.is_empty() {
147
return Series::new_empty(name, &DataType::Null);
148
}
149
150
let dt = series_slice[0].dtype();
151
152
let values_cap = series_slice.iter().fold(0, |acc, s| acc + s.len());
153
154
let mut builder = get_list_builder(dt, values_cap, list_cap, name);
155
for series in series_slice {
156
builder.append_series(series).unwrap();
157
}
158
builder.finish().into_series()
159
}
160
}
161
162
impl<T: AsRef<[Option<Series>]>> NamedFrom<T, [Option<Series>]> for Series {
163
fn new(name: PlSmallStr, s: T) -> Self {
164
let series_slice = s.as_ref();
165
let values_cap = series_slice.iter().fold(0, |acc, opt_s| {
166
acc + opt_s.as_ref().map(|s| s.len()).unwrap_or(0)
167
});
168
let dt = match series_slice.iter().filter_map(|opt| opt.as_ref()).next() {
169
Some(series) => series.dtype(),
170
None => &DataType::Null,
171
};
172
173
let mut builder = get_list_builder(dt, values_cap, series_slice.len(), name);
174
for series in series_slice {
175
builder.append_opt_series(series.as_ref()).unwrap();
176
}
177
builder.finish().into_series()
178
}
179
}
180
impl<'a, T: AsRef<[&'a str]>> NamedFrom<T, [&'a str]> for Series {
181
fn new(name: PlSmallStr, v: T) -> Self {
182
StringChunked::from_slice(name, v.as_ref()).into_series()
183
}
184
}
185
186
impl NamedFrom<&Series, str> for Series {
187
fn new(name: PlSmallStr, s: &Series) -> Self {
188
let mut s = s.clone();
189
s.rename(name);
190
s
191
}
192
}
193
194
impl<'a, T: AsRef<[&'a str]>> NamedFrom<T, [&'a str]> for StringChunked {
195
fn new(name: PlSmallStr, v: T) -> Self {
196
StringChunked::from_slice(name, v.as_ref())
197
}
198
}
199
200
impl<'a, T: AsRef<[Option<&'a str>]>> NamedFrom<T, [Option<&'a str>]> for Series {
201
fn new(name: PlSmallStr, v: T) -> Self {
202
StringChunked::from_slice_options(name, v.as_ref()).into_series()
203
}
204
}
205
206
impl<'a, T: AsRef<[Option<&'a str>]>> NamedFrom<T, [Option<&'a str>]> for StringChunked {
207
fn new(name: PlSmallStr, v: T) -> Self {
208
StringChunked::from_slice_options(name, v.as_ref())
209
}
210
}
211
212
impl<'a, T: AsRef<[Cow<'a, str>]>> NamedFrom<T, [Cow<'a, str>]> for Series {
213
fn new(name: PlSmallStr, v: T) -> Self {
214
StringChunked::from_iter_values(name, v.as_ref().iter().map(|value| value.as_ref()))
215
.into_series()
216
}
217
}
218
219
impl<'a, T: AsRef<[Cow<'a, str>]>> NamedFrom<T, [Cow<'a, str>]> for StringChunked {
220
fn new(name: PlSmallStr, v: T) -> Self {
221
StringChunked::from_iter_values(name, v.as_ref().iter().map(|value| value.as_ref()))
222
}
223
}
224
225
impl<'a, T: AsRef<[Option<Cow<'a, str>>]>> NamedFrom<T, [Option<Cow<'a, str>>]> for Series {
226
fn new(name: PlSmallStr, v: T) -> Self {
227
StringChunked::new(name, v).into_series()
228
}
229
}
230
231
impl<'a, T: AsRef<[Option<Cow<'a, str>>]>> NamedFrom<T, [Option<Cow<'a, str>>]> for StringChunked {
232
fn new(name: PlSmallStr, v: T) -> Self {
233
StringChunked::from_iter_options(
234
name,
235
v.as_ref()
236
.iter()
237
.map(|opt| opt.as_ref().map(|value| value.as_ref())),
238
)
239
}
240
}
241
242
impl<'a, T: AsRef<[&'a [u8]]>> NamedFrom<T, [&'a [u8]]> for Series {
243
fn new(name: PlSmallStr, v: T) -> Self {
244
BinaryChunked::from_slice(name, v.as_ref()).into_series()
245
}
246
}
247
248
impl<'a, T: AsRef<[&'a [u8]]>> NamedFrom<T, [&'a [u8]]> for BinaryChunked {
249
fn new(name: PlSmallStr, v: T) -> Self {
250
BinaryChunked::from_slice(name, v.as_ref())
251
}
252
}
253
254
impl<'a, T: AsRef<[Option<&'a [u8]>]>> NamedFrom<T, [Option<&'a [u8]>]> for Series {
255
fn new(name: PlSmallStr, v: T) -> Self {
256
BinaryChunked::from_slice_options(name, v.as_ref()).into_series()
257
}
258
}
259
260
impl<'a, T: AsRef<[Option<&'a [u8]>]>> NamedFrom<T, [Option<&'a [u8]>]> for BinaryChunked {
261
fn new(name: PlSmallStr, v: T) -> Self {
262
BinaryChunked::from_slice_options(name, v.as_ref())
263
}
264
}
265
266
impl<'a, T: AsRef<[Cow<'a, [u8]>]>> NamedFrom<T, [Cow<'a, [u8]>]> for Series {
267
fn new(name: PlSmallStr, v: T) -> Self {
268
BinaryChunked::from_iter_values(name, v.as_ref().iter().map(|value| value.as_ref()))
269
.into_series()
270
}
271
}
272
273
impl<'a, T: AsRef<[Cow<'a, [u8]>]>> NamedFrom<T, [Cow<'a, [u8]>]> for BinaryChunked {
274
fn new(name: PlSmallStr, v: T) -> Self {
275
BinaryChunked::from_iter_values(name, v.as_ref().iter().map(|value| value.as_ref()))
276
}
277
}
278
279
impl<'a, T: AsRef<[Option<Cow<'a, [u8]>>]>> NamedFrom<T, [Option<Cow<'a, [u8]>>]> for Series {
280
fn new(name: PlSmallStr, v: T) -> Self {
281
BinaryChunked::new(name, v).into_series()
282
}
283
}
284
285
impl<'a, T: AsRef<[Option<Cow<'a, [u8]>>]>> NamedFrom<T, [Option<Cow<'a, [u8]>>]>
286
for BinaryChunked
287
{
288
fn new(name: PlSmallStr, v: T) -> Self {
289
BinaryChunked::from_iter_options(
290
name,
291
v.as_ref()
292
.iter()
293
.map(|opt| opt.as_ref().map(|value| value.as_ref())),
294
)
295
}
296
}
297
298
#[cfg(feature = "dtype-date")]
299
impl<T: AsRef<[NaiveDate]>> NamedFrom<T, [NaiveDate]> for DateChunked {
300
fn new(name: PlSmallStr, v: T) -> Self {
301
DateChunked::from_naive_date(name, v.as_ref().iter().copied())
302
}
303
}
304
305
#[cfg(feature = "dtype-date")]
306
impl<T: AsRef<[NaiveDate]>> NamedFrom<T, [NaiveDate]> for Series {
307
fn new(name: PlSmallStr, v: T) -> Self {
308
DateChunked::new(name, v).into_series()
309
}
310
}
311
312
#[cfg(feature = "dtype-date")]
313
impl<T: AsRef<[Option<NaiveDate>]>> NamedFrom<T, [Option<NaiveDate>]> for DateChunked {
314
fn new(name: PlSmallStr, v: T) -> Self {
315
DateChunked::from_naive_date_options(name, v.as_ref().iter().copied())
316
}
317
}
318
319
#[cfg(feature = "dtype-date")]
320
impl<T: AsRef<[Option<NaiveDate>]>> NamedFrom<T, [Option<NaiveDate>]> for Series {
321
fn new(name: PlSmallStr, v: T) -> Self {
322
DateChunked::new(name, v).into_series()
323
}
324
}
325
326
#[cfg(feature = "dtype-datetime")]
327
impl<T: AsRef<[NaiveDateTime]>> NamedFrom<T, [NaiveDateTime]> for DatetimeChunked {
328
fn new(name: PlSmallStr, v: T) -> Self {
329
DatetimeChunked::from_naive_datetime(
330
name,
331
v.as_ref().iter().copied(),
332
TimeUnit::Milliseconds,
333
)
334
}
335
}
336
337
#[cfg(feature = "dtype-datetime")]
338
impl<T: AsRef<[NaiveDateTime]>> NamedFrom<T, [NaiveDateTime]> for Series {
339
fn new(name: PlSmallStr, v: T) -> Self {
340
DatetimeChunked::new(name, v).into_series()
341
}
342
}
343
344
#[cfg(feature = "dtype-datetime")]
345
impl<T: AsRef<[Option<NaiveDateTime>]>> NamedFrom<T, [Option<NaiveDateTime>]> for DatetimeChunked {
346
fn new(name: PlSmallStr, v: T) -> Self {
347
DatetimeChunked::from_naive_datetime_options(
348
name,
349
v.as_ref().iter().copied(),
350
TimeUnit::Milliseconds,
351
)
352
}
353
}
354
355
#[cfg(feature = "dtype-datetime")]
356
impl<T: AsRef<[Option<NaiveDateTime>]>> NamedFrom<T, [Option<NaiveDateTime>]> for Series {
357
fn new(name: PlSmallStr, v: T) -> Self {
358
DatetimeChunked::new(name, v).into_series()
359
}
360
}
361
362
#[cfg(feature = "dtype-duration")]
363
impl<T: AsRef<[ChronoDuration]>> NamedFrom<T, [ChronoDuration]> for DurationChunked {
364
fn new(name: PlSmallStr, v: T) -> Self {
365
DurationChunked::from_duration(name, v.as_ref().iter().copied(), TimeUnit::Nanoseconds)
366
}
367
}
368
369
#[cfg(feature = "dtype-duration")]
370
impl<T: AsRef<[ChronoDuration]>> NamedFrom<T, [ChronoDuration]> for Series {
371
fn new(name: PlSmallStr, v: T) -> Self {
372
DurationChunked::new(name, v).into_series()
373
}
374
}
375
376
#[cfg(feature = "dtype-duration")]
377
impl<T: AsRef<[Option<ChronoDuration>]>> NamedFrom<T, [Option<ChronoDuration>]>
378
for DurationChunked
379
{
380
fn new(name: PlSmallStr, v: T) -> Self {
381
DurationChunked::from_duration_options(
382
name,
383
v.as_ref().iter().copied(),
384
TimeUnit::Nanoseconds,
385
)
386
}
387
}
388
389
#[cfg(feature = "dtype-duration")]
390
impl<T: AsRef<[Option<ChronoDuration>]>> NamedFrom<T, [Option<ChronoDuration>]> for Series {
391
fn new(name: PlSmallStr, v: T) -> Self {
392
DurationChunked::new(name, v).into_series()
393
}
394
}
395
396
#[cfg(feature = "dtype-time")]
397
impl<T: AsRef<[NaiveTime]>> NamedFrom<T, [NaiveTime]> for TimeChunked {
398
fn new(name: PlSmallStr, v: T) -> Self {
399
TimeChunked::from_naive_time(name, v.as_ref().iter().copied())
400
}
401
}
402
403
#[cfg(feature = "dtype-time")]
404
impl<T: AsRef<[NaiveTime]>> NamedFrom<T, [NaiveTime]> for Series {
405
fn new(name: PlSmallStr, v: T) -> Self {
406
TimeChunked::new(name, v).into_series()
407
}
408
}
409
410
#[cfg(feature = "dtype-time")]
411
impl<T: AsRef<[Option<NaiveTime>]>> NamedFrom<T, [Option<NaiveTime>]> for TimeChunked {
412
fn new(name: PlSmallStr, v: T) -> Self {
413
TimeChunked::from_naive_time_options(name, v.as_ref().iter().copied())
414
}
415
}
416
417
#[cfg(feature = "dtype-time")]
418
impl<T: AsRef<[Option<NaiveTime>]>> NamedFrom<T, [Option<NaiveTime>]> for Series {
419
fn new(name: PlSmallStr, v: T) -> Self {
420
TimeChunked::new(name, v).into_series()
421
}
422
}
423
424
#[cfg(feature = "object")]
425
impl<T: PolarsObject> NamedFrom<&[T], &[T]> for ObjectChunked<T> {
426
fn new(name: PlSmallStr, v: &[T]) -> Self {
427
ObjectChunked::from_slice(name, v)
428
}
429
}
430
431
#[cfg(feature = "object")]
432
impl<T: PolarsObject, S: AsRef<[Option<T>]>> NamedFrom<S, [Option<T>]> for ObjectChunked<T> {
433
fn new(name: PlSmallStr, v: S) -> Self {
434
ObjectChunked::from_slice_options(name, v.as_ref())
435
}
436
}
437
438
impl<T: PolarsNumericType> ChunkedArray<T> {
439
/// Specialization that prevents an allocation
440
/// prefer this over ChunkedArray::new when you have a `Vec<T::Native>` and no null values.
441
pub fn new_vec(name: PlSmallStr, v: Vec<T::Native>) -> Self {
442
ChunkedArray::from_vec(name, v)
443
}
444
}
445
446
/// For any [`ChunkedArray`] and [`Series`]
447
impl<T: IntoSeries> NamedFrom<T, T> for Series {
448
fn new(name: PlSmallStr, t: T) -> Self {
449
let mut s = t.into_series();
450
s.rename(name);
451
s
452
}
453
}
454
455
#[cfg(test)]
456
mod test {
457
use super::*;
458
459
#[cfg(all(
460
feature = "dtype-datetime",
461
feature = "dtype-duration",
462
feature = "dtype-date",
463
feature = "dtype-time"
464
))]
465
#[test]
466
fn test_temporal_df_construction() {
467
// check if we can construct.
468
let _df = df![
469
"date" => [NaiveDate::from_ymd_opt(2021, 1, 1).unwrap()],
470
"datetime" => [NaiveDate::from_ymd_opt(2021, 1, 1).unwrap().and_hms_opt(0, 0, 0).unwrap()],
471
"optional_date" => [Some(NaiveDate::from_ymd_opt(2021, 1, 1).unwrap())],
472
"optional_datetime" => [Some(NaiveDate::from_ymd_opt(2021, 1, 1).unwrap().and_hms_opt(0, 0, 0).unwrap())],
473
"time" => [NaiveTime::from_hms_opt(23, 23, 23).unwrap()],
474
"optional_time" => [Some(NaiveTime::from_hms_opt(23, 23, 23).unwrap())],
475
"duration" => [ChronoDuration::from_std(std::time::Duration::from_secs(10)).unwrap()],
476
"optional_duration" => [Some(ChronoDuration::from_std(std::time::Duration::from_secs(10)).unwrap())],
477
].unwrap();
478
}
479
480
#[test]
481
fn build_series_from_empty_series_vec() {
482
let empty_series = Series::new("test".into(), Vec::<Series>::new());
483
assert_eq!(empty_series.len(), 0);
484
assert_eq!(*empty_series.dtype(), DataType::Null);
485
assert_eq!(empty_series.name().as_str(), "test");
486
}
487
}
488
489