Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
pola-rs
GitHub Repository: pola-rs/polars
Path: blob/main/crates/polars-core/src/series/into.rs
6940 views
1
#[cfg(any(
2
feature = "dtype-datetime",
3
feature = "dtype-date",
4
feature = "dtype-duration",
5
feature = "dtype-time"
6
))]
7
use polars_compute::cast::cast_default as cast;
8
use polars_compute::cast::cast_unchecked;
9
10
use crate::prelude::*;
11
12
impl Series {
13
/// Returns a reference to the Arrow ArrayRef
14
#[inline]
15
pub fn array_ref(&self, chunk_idx: usize) -> &ArrayRef {
16
&self.chunks()[chunk_idx] as &ArrayRef
17
}
18
19
/// Convert a chunk in the Series to the correct Arrow type.
20
/// This conversion is needed because polars doesn't use a
21
/// 1 on 1 mapping for logical/categoricals, etc.
22
pub fn to_arrow(&self, chunk_idx: usize, compat_level: CompatLevel) -> ArrayRef {
23
match self.dtype() {
24
// make sure that we recursively apply all logical types.
25
#[cfg(feature = "dtype-struct")]
26
dt @ DataType::Struct(fields) => {
27
let ca = self.struct_().unwrap();
28
let arr = ca.downcast_chunks().get(chunk_idx).unwrap();
29
let values = arr
30
.values()
31
.iter()
32
.zip(fields.iter())
33
.map(|(values, field)| {
34
let dtype = &field.dtype;
35
let s = unsafe {
36
Series::from_chunks_and_dtype_unchecked(
37
PlSmallStr::EMPTY,
38
vec![values.clone()],
39
&dtype.to_physical(),
40
)
41
.from_physical_unchecked(dtype)
42
.unwrap()
43
};
44
s.to_arrow(0, compat_level)
45
})
46
.collect::<Vec<_>>();
47
StructArray::new(
48
dt.to_arrow(compat_level),
49
arr.len(),
50
values,
51
arr.validity().cloned(),
52
)
53
.boxed()
54
},
55
// special list branch to
56
// make sure that we recursively apply all logical types.
57
DataType::List(inner) => {
58
let ca = self.list().unwrap();
59
let arr = ca.chunks[chunk_idx].clone();
60
let arr = arr.as_any().downcast_ref::<ListArray<i64>>().unwrap();
61
62
let new_values = if let DataType::Null = &**inner {
63
arr.values().clone()
64
} else {
65
// We pass physical arrays and cast to logical before we convert to arrow.
66
let s = unsafe {
67
Series::from_chunks_and_dtype_unchecked(
68
PlSmallStr::EMPTY,
69
vec![arr.values().clone()],
70
&inner.to_physical(),
71
)
72
.from_physical_unchecked(inner)
73
.unwrap()
74
};
75
76
s.to_arrow(0, compat_level)
77
};
78
79
let dtype = self.dtype().to_arrow(compat_level);
80
let arr = ListArray::<i64>::new(
81
dtype,
82
arr.offsets().clone(),
83
new_values,
84
arr.validity().cloned(),
85
);
86
Box::new(arr)
87
},
88
#[cfg(feature = "dtype-array")]
89
DataType::Array(inner, width) => {
90
let ca = self.array().unwrap();
91
let arr = ca.chunks[chunk_idx].clone();
92
let arr = arr.as_any().downcast_ref::<FixedSizeListArray>().unwrap();
93
94
let new_values = if let DataType::Null = &**inner {
95
arr.values().clone()
96
} else {
97
let s = unsafe {
98
Series::from_chunks_and_dtype_unchecked(
99
PlSmallStr::EMPTY,
100
vec![arr.values().clone()],
101
&inner.to_physical(),
102
)
103
.from_physical_unchecked(inner)
104
.unwrap()
105
};
106
107
s.to_arrow(0, compat_level)
108
};
109
110
let dtype =
111
FixedSizeListArray::default_datatype(inner.to_arrow(compat_level), *width);
112
let arr =
113
FixedSizeListArray::new(dtype, arr.len(), new_values, arr.validity().cloned());
114
Box::new(arr)
115
},
116
#[cfg(feature = "dtype-categorical")]
117
dt @ (DataType::Categorical(_, _) | DataType::Enum(_, _)) => {
118
with_match_categorical_physical_type!(dt.cat_physical().unwrap(), |$C| {
119
let ca = self.cat::<$C>().unwrap();
120
let arr = ca.physical().chunks()[chunk_idx].clone();
121
unsafe {
122
let new_phys = ChunkedArray::from_chunks(PlSmallStr::EMPTY, vec![arr]);
123
let new = CategoricalChunked::<$C>::from_cats_and_dtype_unchecked(new_phys, dt.clone());
124
new.to_arrow(compat_level).boxed()
125
}
126
})
127
},
128
#[cfg(feature = "dtype-date")]
129
DataType::Date => cast(
130
&*self.chunks()[chunk_idx],
131
&DataType::Date.to_arrow(compat_level),
132
)
133
.unwrap(),
134
#[cfg(feature = "dtype-datetime")]
135
DataType::Datetime(_, _) => cast(
136
&*self.chunks()[chunk_idx],
137
&self.dtype().to_arrow(compat_level),
138
)
139
.unwrap(),
140
#[cfg(feature = "dtype-duration")]
141
DataType::Duration(_) => cast(
142
&*self.chunks()[chunk_idx],
143
&self.dtype().to_arrow(compat_level),
144
)
145
.unwrap(),
146
#[cfg(feature = "dtype-time")]
147
DataType::Time => cast(
148
&*self.chunks()[chunk_idx],
149
&DataType::Time.to_arrow(compat_level),
150
)
151
.unwrap(),
152
#[cfg(feature = "dtype-decimal")]
153
DataType::Decimal(_, _) => self.decimal().unwrap().physical().chunks()[chunk_idx]
154
.as_any()
155
.downcast_ref::<PrimitiveArray<i128>>()
156
.unwrap()
157
.clone()
158
.to(self.dtype().to_arrow(CompatLevel::newest()))
159
.to_boxed(),
160
#[cfg(feature = "object")]
161
DataType::Object(_) => {
162
use crate::chunked_array::object::builder::object_series_to_arrow_array;
163
if self.chunks().len() == 1 && chunk_idx == 0 {
164
object_series_to_arrow_array(self)
165
} else {
166
// we slice the series to only that chunk
167
let offset = self.chunks()[..chunk_idx]
168
.iter()
169
.map(|arr| arr.len())
170
.sum::<usize>() as i64;
171
let len = self.chunks()[chunk_idx].len();
172
let s = self.slice(offset, len);
173
object_series_to_arrow_array(&s)
174
}
175
},
176
DataType::String => {
177
if compat_level.0 >= 1 {
178
self.array_ref(chunk_idx).clone()
179
} else {
180
let arr = self.array_ref(chunk_idx);
181
cast_unchecked(arr.as_ref(), &ArrowDataType::LargeUtf8).unwrap()
182
}
183
},
184
DataType::Binary => {
185
if compat_level.0 >= 1 {
186
self.array_ref(chunk_idx).clone()
187
} else {
188
let arr = self.array_ref(chunk_idx);
189
cast_unchecked(arr.as_ref(), &ArrowDataType::LargeBinary).unwrap()
190
}
191
},
192
_ => self.array_ref(chunk_idx).clone(),
193
}
194
}
195
}
196
197