Skip to content

Commit

Permalink
python: dt.timestamp dt.to_python_datetime
Browse files Browse the repository at this point in the history
  • Loading branch information
ritchie46 committed Jun 1, 2021
1 parent 2cddb53 commit cc7bb27
Show file tree
Hide file tree
Showing 13 changed files with 268 additions and 100 deletions.
4 changes: 2 additions & 2 deletions polars/polars-core/src/chunked_array/object/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use arrow::array::{Array, ArrayRef, BooleanBufferBuilder, JsonEqual};
use arrow::bitmap::Bitmap;
use serde_json::Value;
use std::any::Any;
use std::fmt::Debug;
use std::fmt::{Debug, Display};
use std::sync::Arc;

#[derive(Debug, Clone)]
Expand All @@ -22,7 +22,7 @@ where
pub(crate) len: usize,
}

pub trait PolarsObject: Any + Debug + Clone + Send + Sync + Default {
pub trait PolarsObject: Any + Debug + Clone + Send + Sync + Default + Display {
fn type_name() -> &'static str;
}

Expand Down
65 changes: 39 additions & 26 deletions polars/polars-core/src/fmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -126,34 +126,23 @@ fn format_object_array(
name: &str,
array_type: &str,
) -> fmt::Result {
write![f, "{}: '{}' [object]\n[\n", array_type, name]?;

for i in 0..limit {
let v = object.get(i);
match v {
AnyValue::Null => writeln!(f, "\tnull")?,
_ => writeln!(f, "\tobject")?,
}
}

write![f, "]"]
}

#[cfg(feature = "object")]
macro_rules! format_object_array {
($limit:expr, $f:expr, $object:expr, $name:expr, $array_type: expr) => {{
write![$f, "{}: '{}' [object]\n[\n", $array_type, $name]?;
match object.dtype() {
DataType::Object(inner_type) => {
write![
f,
"{}: '{}' [object({})]\n[\n",
array_type, name, inner_type
]?;

for i in 0..$limit {
let v = $object.get_any_value(i);
match v {
AnyValue::Null => writeln!($f, "\tnull")?,
_ => writeln!($f, "\tobject")?,
for i in 0..limit {
let v = object.str_value(i);
write!(f, "\t{}\n", v)?;
}
}

write![$f, "]"]
}};
write![f, "]"]
}
_ => unreachable!(),
}
}

macro_rules! set_limit {
Expand Down Expand Up @@ -209,10 +198,34 @@ where
{
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
let limit = set_limit!(self);
format_object_array!(limit, f, self, self.name(), "ChunkedArray")

let taker = self.take_rand();
match self.dtype() {
DataType::Object(inner_type) => {
write![
f,
"{}: '{}' [object({})]\n[\n",
"ChunkedArray",
self.name(),
inner_type
]?;
for i in 0..limit {
match taker.get(i) {
None => writeln!(f, "\tnull")?,
Some(val) => writeln!(f, "\t{}", val)?,
};
}
}
_ => unreachable!(),
}
Ok(())
}
}

pub trait FormatSeries {
fn fmt_series(f: &mut Formatter<'_>) -> fmt::Result;
}

impl Debug for Series {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
let limit = set_limit!(self);
Expand Down
14 changes: 12 additions & 2 deletions polars/polars-core/src/series/implementations/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::series::private::PrivateSeries;
use arrow::array::{ArrayData, ArrayRef};
use arrow::buffer::Buffer;
use std::any::Any;
use std::borrow::Cow;

#[cfg(feature = "object")]
impl<T> IntoSeries for ObjectChunked<T>
Expand All @@ -19,7 +20,17 @@ where

#[cfg(feature = "object")]
#[cfg_attr(docsrs, doc(cfg(feature = "object")))]
impl<T> PrivateSeries for SeriesWrap<ObjectChunked<T>> where T: PolarsObject {}
impl<T> PrivateSeries for SeriesWrap<ObjectChunked<T>>
where
T: PolarsObject,
{
fn str_value(&self, index: usize) -> Cow<str> {
match (&self.0).get(index) {
None => Cow::Borrowed("null"),
Some(val) => Cow::Owned(format!("{}", val).to_string()),
}
}
}
#[cfg(feature = "object")]
#[cfg_attr(docsrs, doc(cfg(feature = "object")))]
impl<T> SeriesTrait for SeriesWrap<ObjectChunked<T>>
Expand Down Expand Up @@ -86,7 +97,6 @@ where
}

unsafe fn take_unchecked(&self, idx: &UInt32Chunked) -> Result<Series> {
use std::borrow::Cow;
let idx = if idx.chunks.len() > 1 {
Cow::Owned(idx.rechunk())
} else {
Expand Down
20 changes: 20 additions & 0 deletions polars/polars-core/src/series/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ pub(crate) mod private {
use crate::frame::groupby::GroupTuples;

use ahash::RandomState;
use std::borrow::Cow;

pub trait PrivateSeries {
unsafe fn equal_element(
Expand Down Expand Up @@ -151,6 +152,10 @@ pub(crate) mod private {
"argsort_multiple is not implemented for this Series".into(),
))
}
#[cfg(feature = "object")]
fn str_value(&self, _index: usize) -> Cow<str> {
unimplemented!()
}
}
}

Expand Down Expand Up @@ -900,6 +905,21 @@ pub trait SeriesTrait: Send + Sync + private::PrivateSeries {
}
}

#[cfg(feature = "temporal")]
#[cfg_attr(docsrs, doc(cfg(feature = "temporal")))]
/// Convert date(time) object to timestamp in ms.
fn timestamp(&self) -> Result<Int64Chunked> {
match self.dtype() {
DataType::Date32 => self
.date32()
.map(|ca| (ca.cast::<Int64Type>().unwrap() * 1000)),
DataType::Date64 => self.date64().map(|ca| ca.cast::<Int64Type>().unwrap()),
_ => Err(PolarsError::InvalidOperation(
format!("operation not supported on dtype {:?}", self.dtype()).into(),
)),
}
}

/// Clone inner ChunkedArray and wrap in a new Arc
fn clone_inner(&self) -> Arc<dyn SeriesTrait> {
unimplemented!()
Expand Down
37 changes: 18 additions & 19 deletions py-polars/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 4 additions & 4 deletions py-polars/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ polars-core = {path = "../polars/polars-core", default-features = false}
pyo3 = {version = "0.13", features = ["abi3-py36", "extension-module"] }
libc = "0.2"
thiserror = "1.0.20"
numpy = "0.13.0"
ndarray = "0.14.0"
numpy = "0.13"
ndarray = "0.14"
mimalloc = { version = "*", default-features = false}

[dependencies.polars]
Expand Down Expand Up @@ -58,12 +58,12 @@ name = "polars"
requires-dist = ["numpy", "pyarrow==4.0"]

[profile.release]
#codegen-units = 1
codegen-units = 1

# This is ignored here; would be set in .cargo/config.toml.
# Should not be used when packaging
# target-cpu = "native"
#lto = "fat"
lto = "fat"

#[profile.dev]
#opt-level = 1
16 changes: 16 additions & 0 deletions py-polars/polars/series.py
Original file line number Diff line number Diff line change
Expand Up @@ -1755,6 +1755,22 @@ def nanosecond(self):
"""
return wrap_s(self._s.nanosecond())

def timestamp(self) -> "Series":
"""
Return timestamp in ms as Int64 type.
"""
return wrap_s(self._s.timestamp())

def to_python_datetime(self) -> "Series":
"""
Go from Date32/Date64 to python DataTime objects
"""
from datetime import datetime

return (self.timestamp() // 1000).apply(
lambda ts: datetime.fromtimestamp(ts), datatypes.Object
)


class SeriesIter:
"""
Expand Down
29 changes: 29 additions & 0 deletions py-polars/src/apply/mod.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
pub mod dataframe;
pub mod series;
use crate::prelude::ObjectValue;
use polars::chunked_array::builder::get_list_builder;
use polars::prelude::*;
use polars_core::utils::CustomIterTools;
use pyo3::PyObject;

pub trait PyArrowPrimitiveType: PolarsPrimitiveType {}

Expand Down Expand Up @@ -79,6 +81,33 @@ fn iterator_to_bool(
ca
}

fn iterator_to_object(
it: impl Iterator<Item = Option<ObjectValue>>,
init_null_count: usize,
first_value: Option<ObjectValue>,
name: &str,
capacity: usize,
) -> ObjectChunked<ObjectValue> {
let mut ca: ObjectChunked<ObjectValue> = if init_null_count > 0 {
(0..init_null_count)
.map(|_| None)
.chain(std::iter::once(first_value))
.chain(it)
.trust_my_length(capacity)
.collect()
} else if first_value.is_some() {
std::iter::once(first_value)
.chain(it)
.trust_my_length(capacity)
.collect()
} else {
it.collect()
};
debug_assert_eq!(ca.len(), capacity);
ca.rename(name);
ca
}

fn iterator_to_utf8<'a>(
it: impl Iterator<Item = Option<&'a str>>,
init_null_count: usize,
Expand Down

0 comments on commit cc7bb27

Please sign in to comment.