强制类型转换
强制类型转换会将列的底层数据类型转换为新的数据类型, 可以通过cast
函数进行
该函数包含一个参数strict
, 用于确定Polars在遇到无法从源数据类型转换为目标数据类型的值时的行为
默认为strict=True
, Polars会抛出错误,通知用户转换失败, 同时提供无法转换的值得相信信息. 否则任何无法转换的值都会被静默转换为null
基本示例
1import polars as pl
2
3df = pl.DataFrame(
4 {
5 "integers": [1, 2, 3],
6 "big_integers": [10000002, 2, 30000003],
7 "floats": [4.0, 5.8, -6.3],
8 }
9)
10
11print(df)
1shape: (3, 3)
2┌──────────┬──────────────┬────────┐
3│ integers ┆ big_integers ┆ floats │
4│ --- ┆ --- ┆ --- │
5│ i64 ┆ i64 ┆ f64 │
6╞══════════╪══════════════╪════════╡
7│ 1 ┆ 10000002 ┆ 4.0 │
8│ 2 ┆ 2 ┆ 5.8 │
9│ 3 ┆ 30000003 ┆ -6.3 │
10└──────────┴──────────────┴────────┘
下面代码将i64类型的数据转换为f32, 将f64转换为i32, 只需要使用.cast()
方法即可, 需要注意浮点数转换为整数时, 丢失精度
1result = df.select(
2 pl.col("integers").cast(pl.Float32).alias("integers_as_floats"),
3 pl.col("floats").cast(pl.Int32).alias("floats_as_integers"),
4)
5print(result)
1shape: (3, 2)
2┌────────────────────┬────────────────────┐
3│ integers_as_floats ┆ floats_as_integers │
4│ --- ┆ --- │
5│ f32 ┆ i32 │
6╞════════════════════╪════════════════════╡
7│ 1.0 ┆ 4 │
8│ 2.0 ┆ 5 │
9│ 3.0 ┆ -6 │
10└────────────────────┴────────────────────┘
转换为低容量类型以减少内存占用
将i64->i16, f64->f32可以减少内存占用, 又不影响数据精度
WARNING
请确保转换后的数据类型可以容纳数据, 否则Polars会报错
1print(f"类型转换之前内存占用: {df.estimated_size()} bytes")
2
3result = df.with_columns(
4 pl.col("integers").cast(pl.Int16),
5 pl.col("floats").cast(pl.Float32),
6)
7print(result)
8print(f"类型转换之后内存占用: {result.estimated_size()} bytes")
1类型转换之前内存占用: 72 bytes
2shape: (3, 3)
3┌──────────┬──────────────┬────────┐
4│ integers ┆ big_integers ┆ floats │
5│ --- ┆ --- ┆ --- │
6│ i16 ┆ i64 ┆ f32 │
7╞══════════╪══════════════╪════════╡
8│ 1 ┆ 10000002 ┆ 4.0 │
9│ 2 ┆ 2 ┆ 5.8 │
10│ 3 ┆ 30000003 ┆ -6.3 │
11└──────────┴──────────────┴────────┘
12类型转换之后内存占用: 42 bytes
转换时类型不匹配报错
如果转换时数据类型不匹配, Polars会抛出异常, 比如下面的例子中big_integers列转换成i8时, i8类型显然无法容纳第一个值和第三个值
TIP
自己在使用时, 可以先试用max函数看下最大值, 或者使用try except
包裹处理错误
1from polars.exceptions import InvalidOperationError
2
3try:
4 result = df.select(pl.col("big_integers").cast(pl.Int8))
5 print(result)
6except InvalidOperationError as err:
7 print(err)
1conversion from `i64` to `i8` failed in column 'big_integers' for 2 out of 3 values: [10000002, 30000003]
使用strict=False
将溢出值转换为null
下面的例子中将i64转换为i8, 第一个和第三个值显然会溢出, 使用strict=False
可以将溢出值转换为null
1result = df.select(pl.col("big_integers").cast(pl.Int8, strict=False))
2print(result)
1shape: (3, 1)
2┌──────────────┐
3│ big_integers │
4│ --- │
5│ i8 │
6╞══════════════╡
7│ null │
8│ 2 │
9│ null │
10└──────────────┘
将字符串转换为数字数据类型
表示数字的字符串可以通过强制类型转换转换为相应的数据类型, 反向转换也是可以的
1df = pl.DataFrame(
2 {
3 "integers_as_strings": ["1", "2", "3"],
4 "floats_as_strings": ["4.0", "5.8", "-6.3"],
5 "floats": [4.0, 5.8, -6.3],
6 }
7)
8
9result = df.select(
10 pl.col("integers_as_strings").cast(pl.Int32),
11 pl.col("floats_as_strings").cast(pl.Float64),
12 pl.col("floats").cast(pl.String),
13)
14print(result)
1shape: (3, 3)
2┌─────────────────────┬───────────────────┬────────┐
3│ integers_as_strings ┆ floats_as_strings ┆ floats │
4│ --- ┆ --- ┆ --- │
5│ i32 ┆ f64 ┆ str │
6╞═════════════════════╪═══════════════════╪════════╡
7│ 1 ┆ 4.0 ┆ 4.0 │
8│ 2 ┆ 5.8 ┆ 5.8 │
9│ 3 ┆ -6.3 ┆ -6.3 │
10└─────────────────────┴───────────────────┴────────┘
如果列包含非数字值或者格式错误, Polars会抛出错误并给出详细的错误信息, 可以设置strict=False
绕过错误获取null值
布尔类型转换
-
数值转换为布尔类型时, 0转换为false, 非0转换为true
-
布尔转换为数值类型时, true转换为1, false转换为0
1df = pl.DataFrame(
2 {
3 "integers": [-1, 0, 2, 3, 4],
4 "floats": [0.0, 1.0, 2.0, 3.0, 4.1],
5 "bools": [True, False, True, False, True],
6 }
7)
8
9result = df.select(
10 pl.col("integers").cast(pl.Boolean),
11 pl.col("floats").cast(pl.Boolean),
12 pl.col("bools").cast(pl.Int8),
13)
14print(result)
1shape: (5, 3)
2┌──────────┬────────┬───────┐
3│ integers ┆ floats ┆ bools │
4│ --- ┆ --- ┆ --- │
5│ bool ┆ bool ┆ i8 │
6╞══════════╪════════╪═══════╡
7│ true ┆ false ┆ 1 │
8│ false ┆ true ┆ 0 │
9│ true ┆ true ┆ 1 │
10│ true ┆ true ┆ 0 │
11│ true ┆ true ┆ 1 │
12└──────────┴────────┴───────┘
时间数据类型处理
所有时间数据类型的数据在内部都表示为: 从参考时间(纪元)到现在所经过的时间单位数, Unix纪元: 1970 年 1 月 1 日 00:00:00 UTC
Date
: 存储自纪元以来的天数
Datetime
: 存储自纪元以来的毫秒数(ms
)
Time
: 时间单位是纳秒(ns
)
Polars允许在数字类型和事件类型数据之间进行转换
标准库datetime基本示例
1from datetime import date, datetime, time
2
3print(date(1970,1,1))
4print(datetime(1970,1,1,0,0,0))
5print(time(0,0,1))
11970-01-01
21970-01-01 00:00:00
300:00:01
时间转换为数字
1from datetime import date, datetime, time
2import polars as pl
3df = pl.DataFrame(
4 {
5 "date": [
6 date(1970, 1, 1), # 转换之后是0, 因为是从这天开始计算的
7 date(1970, 1, 10), # 转换之后是9, 10-1=9, 第九天
8 ],
9 "datetime": [
10 datetime(1970, 1, 1, 0, 0, 0), # 转换之后是0
11 datetime(1970, 1, 1, 0, 1, 0), # 纪元1分钟之后, 1分钟60秒, 一共是60_000毫秒, 60_000_000毫秒
12 ],
13 "time": [
14 time(0, 0, 0), # time计算起点是每天的午夜零点, 转换之后是0
15 time(0, 0, 1), # 1s之后, 一共是1_000_000_000纳秒
16 ],
17 }
18)
19print(df)
20result = df.select(
21 pl.col("date").cast(pl.Int64).alias("days_since_epoch"),
22 pl.col("datetime").cast(pl.Int64).alias("us_since_epoch"),
23 pl.col("time").cast(pl.Int64).alias("ns_since_midnight"),
24)
25print(result)
1shape: (2, 3)
2┌────────────┬─────────────────────┬──────────┐
3│ date ┆ datetime ┆ time │
4│ --- ┆ --- ┆ --- │
5│ date ┆ datetime[μs] ┆ time │
6╞════════════╪═════════════════════╪══════════╡
7│ 1970-01-01 ┆ 1970-01-01 00:00:00 ┆ 00:00:00 │
8│ 1970-01-10 ┆ 1970-01-01 00:01:00 ┆ 00:00:01 │
9└────────────┴─────────────────────┴──────────┘
10shape: (2, 3)
11┌──────────────────┬────────────────┬───────────────────┐
12│ days_since_epoch ┆ us_since_epoch ┆ ns_since_midnight │
13│ --- ┆ --- ┆ --- │
14│ i64 ┆ i64 ┆ i64 │
15╞══════════════════╪════════════════╪═══════════════════╡
16│ 0 ┆ 0 ┆ 0 │
17│ 9 ┆ 60000000 ┆ 1000000000 │
18└──────────────────┴────────────────┴───────────────────┘
时间类型和字符串互转
- 时间类型转换为字符串:
.str.to_string()
- 字符串转换为时间类型:
.str.to_datetime()
1df = pl.DataFrame(
2 {
3 "date": [date(2022, 1, 1), date(2022, 1, 2)],
4 "string": ["2022-01-01", "2022-01-02"],
5 "time":[time(0,0,0), time(1,0,0)]
6 }
7)
8
9result = df.select(
10 pl.col("date").dt.to_string("%Y-%m-%d"),
11 pl.col("string").str.to_datetime("%Y-%m-%d"),
12 pl.col("time").dt.to_string("%H:%M:%S")
13)
14print(result)
1shape: (2, 3)
2┌────────────┬─────────────────────┬──────────┐
3│ date ┆ string ┆ time │
4│ --- ┆ --- ┆ --- │
5│ str ┆ datetime[μs] ┆ str │
6╞════════════╪═════════════════════╪══════════╡
7│ 2022-01-01 ┆ 2022-01-01 00:00:00 ┆ 00:00:00 │
8│ 2022-01-02 ┆ 2022-01-02 00:00:00 ┆ 01:00:00 │
9└────────────┴─────────────────────┴──────────┘
TIP
str.to_datetime
具有支持时区功能的其他选项, 更多信息可以参考官方API文档