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