Polars使用指南(二)

上一篇文章中,我们介绍了Polars的优势和Polars.Series的常用API,本篇文章我们继续介绍Polars.Series的扩展API。

对于一些特殊的数据类型,如 pl.Array、list、str 等,Polars.Series 提供了基于属性的直接操作API,如果可以使用下述API实现的功能,应尽量避免使用 map_elements,因为效率更高。

1. Series.arr

Series中的元素可能不是简单数据类型,而是等长的数组,此时则可以直接使用polars内置的arr属性方法。

需要注意使用Series.arr的前提是Series的元素类型必须是pl.Array,而pl.Array需要指定长度,所以该系列的Series每个元素的长度都是固定的,如果Array不能满足需求,则可以使用第2节的Series.list。

import polars as pl

s = pl.Series("a", [[1, 2], [4, 3]], dtype=pl.Array(pl.Int64, 2))
s.arr.max()
# 结果
[
    2
    4
]
s.arr.min()
s.arr.sum()
# 把array转为list
s.arr.to_list()
# 去重,maintain_order 表示是否保持原始顺序,True 一般会降低性能
Series.arr.unique(*, maintain_order: bool = False) → Series
# 与和或
s.arr.all()
s.arr.any()

2. Series.list

list是比arr更灵活的结构,尤其是不再受限于固定长度。

import polars as pl

s = pl.Series(
    [[True, True], [False, True], [False, False], [None], [], None],
    dtype=pl.List(pl.Boolean),
)
s.list.all()
# 结果
[
    true
    false
    false
    true
    true
    null
]
s.list.any()
# 删除所有list中的空值,注意不是删除整个list元素,只删除每个list中的空值
s.list.drop_nulls()
# 每个list的最大/最小值
s.list.max()
s.list.min()
# 每个list的最大/最小值索引
s.list.arg_max()
s.list.arg_min()
# 每个list的和/均值
Series.list.sum() → Series
Series.list.mean() → Series
# 每个list元素个数,null也计算在内
Series.list.len() → Series
# 每个list合并其他list或者其他Series对应数据
Series.list.concat(other: list[Series] | Series | list[Any])
# 每个list第一个/最后一个值
Series.list.first() → Series
Series.list.last() → Series
# 每个list前/后n个值
Series.list.head(n: int | Expr = 5) → Series
Series.list.tail(n: int | Expr = 5) → Series
# 按索引取每个list中值
Series.list.get(index: int | Series | list[int]) → Series
# 按索引取每个list中值
Series.list.gather(
	indices: Series | list[int] | list[list[int]],
	*,
	null_on_oob: bool = False,
) → Series

# 压扁
s = pl.Series("a", [[1, 2, 3], [4, 5, 6]])
s.list.explode()  # 结果[1 2 3 4 5 6]
# 每个list内的偏差,null_behavior:{‘ignore’, ‘drop’}
Series.list.diff(n: int = 1, null_behavior: NullBehavior = 'ignore') 
# 每个list内元素值的频率
Series.list.count_matches(
	element: float | str | bool | int | date | datetime | time | Expr,
)
# 每个list是否包含给定值
Series.list.contains(item: float | str | bool | int | date | datetime)
# 翻转每个list
Series.list.reverse() → Series
# 每个list中元素听过分隔符拼接为一个值(每行只有一个str值),list中元素必须为字符串
Series.list.join(separator: IntoExpr) → Series
# 每个list去重
Series.list.unique(*, maintain_order: bool = False) → Series
# 每个list排序
Series.list.sort(*, descending: bool = False) → Series
# 每个list做切片,offset:起始位置,length:长度
Series.list.slice(offset: int | Expr, length: int | Expr | None = None) → Series
# 每个list平移
Series.list.shift(n: int | IntoExprColumn = 1) → Series

# 两个list类型Series每行的并集
Series.list.set_union(other: Series) → Series
# 两个list类型Series每行的交集
Series.list.set_intersection(other: Series) → Series
# 两个list类型Series每行的差集
Series.list.set_difference(other: Series) → Series

# 执行任意表达式,用于实现复杂需求
Series.list.eval(expr: Expr, *, parallel: bool = False) → Series
df = pl.DataFrame({"a": [1, 8, 3], "b": [4, 5, 2]})
df.with_columns(
    pl.concat_list(["a", "b"]).list.eval(pl.element().rank()).alias("rank")
)
# 结果
┌─────┬─────┬────────────┐
│ a   ┆ b   ┆ rank       │
│ ---------        │
│ i64 ┆ i64 ┆ list[f64]  │
╞═════╪═════╪════════════╡
│ 14[1.0, 2.0] │
│ 85[2.0, 1.0] │
│ 32[2.0, 1.0] │
└─────┴─────┴────────────┘

# list转arr,width:arr宽度,需保证每个list等长
Series.list.to_array(width: int) → Series

3. Series.str

str 类型数据也是最常用的数据操作类型。

# 把Series中的所有str类型元素通过delimiter拼接为一个值,返回值是只有一个元素的Series;strict 如果异常,是引发异常,还是返回空值
Series.str.concat(delimiter: str = '-', *, ignore_nulls: bool = True) → Series
# 是否包含指定正则表达式,返回布尔类型,literal:True表示按正则解析pattern,False表示按纯字符串解析pattern,
Series.str.contains(
	pattern: str | Expr,
	*,
	literal: bool = False,
	strict: bool = True,
) → Series
s = pl.Series("s", ["AAA", "aAa", "aaa"])
# 不区分大小写,(?iLmsuxU) 语法
s.str.contains("(?i)AA").to_list()

# 包含patterns中任一值则返回True
Series.str.contains_any(
	patterns: Series | list[str],
	*,
	ascii_case_insensitive: bool = False,
) → Series

# 是否以指定字符串开头
Series.str.starts_with(prefix: str | Expr) → Series
# 是否以指定字符串结尾
Series.str.ends_with(suffix: str | Expr) → Series

# 字符串压扁
Series.str.explode() → Series
s = pl.Series("a", ["foo", "bar"])
s.str.explode()  # 结果 ["f" "o" "o" "b" "a" "r"]

# 根据pattern正则提取要素
Series.str.extract(pattern: str, group_index: int = 1) → Series
# 根据pattern正则提取所有匹配到的要素,返回是list类型的Series
Series.str.extract_all(pattern: str | Series) → Series
# 根据pattern正则提取所有group
Series.str.extract_groups(pattern: str) → Series

# 按照json解析元素
Series.str.json_decode(
	dtype: PolarsDataType | None = None,
	infer_schema_length: int | None = 100,
) → Series
# 使用提供的JSONPath表达式提取json字符串的第一个匹配。如果遇到无效的json字符串,抛出错误。所有返回值将被强制转换为String,而不管原始值是什么。
Series.str.json_path_match(json_path: str) → Series
df = pl.DataFrame(
    {"json_val": ['{"a":"1"}', None, '{"a":2}', '{"a":2.1}', '{"a":true}']}
)
df.select(pl.col("json_val").str.json_path_match("$.a"))[:, 0]
# 结果
[
    "1"
    null
    "2"
    "2.1"
    "true"
]

# 每个str的字符长度
Series.str.len_chars() → Series
# 每个str的字节长度,性能比len_chars高
Series.str.len_bytes() → Series

# 根据给定字符从左边填充字符串到指定长度,长度等于或大于此值的字符串将按原样返回。
Series.str.pad_start(length: int, fill_char: str = ' ') → Series
# 根据给定字符从右边填充字符串到指定长度,长度等于或大于此值的字符串将按原样返回。
Series.str.pad_end(length: int, fill_char: str = ' ') → Series

# 字符串替换,literal默认False,表示按照正则解析pattern,此时n只能为;如果literal为True,则表示按纯字符串解析pattern,此时n可以大于1。n表示要替换的数量
Series.str.replace(
	pattern: str,
	value: str,
	*,
	literal: bool = False,
	n: int = 1,
) → Series
# 替换所有匹配的字符串
Series.str.replace_all(pattern: str, value: str, *, literal: bool = False) → Series
# 多对多替换,patterns和replace_with一一对应
Series.str.replace_many(
	patterns: Series | list[str],
	replace_with: Series | list[str] | str,
	*,
	ascii_case_insensitive: bool = False,
) → Series

# 翻转字符串
Series.str.reverse() → Series
# 字符串切片,offset为负表示最后n位
Series.str.slice(offset: int, length: int | None = None) → Series
# 分隔字符串
Series.str.split(by: IntoExpr, *, inclusive: bool = False) → Series
# 删除开头和结尾的指定字符集,默认是删除空格
Series.str.strip_chars(characters: IntoExprColumn | None = None) → Series
# 删除开头的指定字符集,默认是删除空格
Series.str.strip_chars_start(characters: IntoExprColumn | None = None) → Series
# 删除结尾的指定字符集,默认是删除空格
Series.str.strip_chars_end(characters: IntoExprColumn | None = None) → Series
# 删除指定字符串前缀,同strip_chars_start
Series.str.strip_prefix(prefix: IntoExpr) → Series
# 删除指定字符串后缀,同strip_chars_end
Series.str.strip_suffix(suffix: IntoExpr) → Series

# 字符串转为日期,dtype要转换的类型 Date、 Datetime、 or Time;format如果没指定,则程序自己尝试解析(不建议);
# strict:如果转换失败,是否引发异常;
# ambiguous,如果程序解析发现结果不确定(二义性等),应该如何处理,{'raise' (default): 引发异常,'earliest': 使用最早的日期时间,'latest':使用最晚的日期时间}
Series.str.strptime(
	dtype: PolarsTemporalType,
	format: str | None = None,
	*,
	strict: bool = True,
	exact: bool = True,
	cache: bool = True,
	ambiguous: Ambiguous | Series = 'raise',
) → Series
# to_date
Series.str.to_date(
	format: str | None = None,
	*,
	strict: bool = True,
	exact: bool = True,
	cache: bool = True,
) → Series
# to_datetime,time_unit:{None, 'us', 'ns', 'ms'}
Series.str.to_datetime(
	format: str | None = None,
	*,
	time_unit: TimeUnit | None = None,
	time_zone: str | None = None,
	strict: bool = True,
	exact: bool = True,
	cache: bool = True,
	ambiguous: Ambiguous | Series = 'raise',
) → Series
s = pl.Series(["2020-01-01 01:00Z", "2020-01-01 02:00Z"])
s.str.to_datetime("%Y-%m-%d %H:%M%#z")
# to_time
Series.str.to_time(
	format: str | None = None,
	*,
	strict: bool = True,
	cache: bool = True,
) → Series

# 根据指定进制转换为整型
Series.str.to_integer(*, base: int = 10, strict: bool = True) → Series
s = pl.Series("bin", ["110", "101", "010", "invalid"])
s.str.to_integer(base=2, strict=False)
# 转换为decimal,inference_length 确定精度和有效位数
Series.str.to_decimal(inference_length: int = 100) → Series
s = pl.Series(
    ["40.12", "3420.13", "120134.19", "3212.98", "12.90", "143.09", "143.9"]
)
s.str.to_decimal()
# 结果
[
    40.12
    3420.13
    120134.19
    3212.98
    12.90
    143.09
    143.90
]
# 转小写
Series.str.to_lowercase() → Series
# 转大写
Series.str.to_uppercase() → Series
# 将句子每个单词首字母改为大写,其它字母小写
Series.str.to_titlecase() → Series
# 对数字类型字符串前面填充0到指定长度,如果前缀是-(负数),则在-后填充。使用时,需要先把数值类型转为str,然后调用
Series.str.zfill(length: int) → Series
s = pl.Series([-1, 123, 999999, None])
s.cast(pl.String).str.zfill(4)

4. Series.dt

时间类型Series API。除下面列出API外,Series.dt 也支持分桶、时区转换等操作,具体可参考官方文档

# 组合两个日期,如果s有时间字段,则使用time替换s的时间字段;若s无时间字段(date类型),则把time添加为时间属性
Series.dt.combine(time: dt.time | Series, time_unit: TimeUnit = 'us') → Expr

# 提取date属性(结果是polars.Date类型的Series)
Series.dt.date() → Series
# 提取datetime属性(结果是polars.Datetime类型的Series)
Series.dt.datetime() → Series
# 提取time属性(结果是polars.Time类型的Series)
Series.dt.time() → Series
# 提取年属性
Series.dt.year() → Series
# 提取季节属性
Series.dt.quarter() → Series
# 提取month属性
Series.dt.month() → Series
# 提取week属性,一年中的第几周
Series.dt.week() → Series
# 提取weekday属性,一周第几天,范围1~7,星期一为1,星期天为7
Series.dt.weekday() → Series
# 提取day属性(结果是polars.Int8类型的Series)
Series.dt.day() → Series
# 提取hour属性
Series.dt.hour() → Series
# 提取minute属性
Series.dt.minute() → Series
# 提取second属性,如果fractional为True,则返回小数(包含秒、毫秒等)
Series.dt.second(*, fractional: bool = False) → Series
# 提取毫秒属性
Series.dt.millisecond() → Series
# 提取微秒属性
Series.dt.microsecond() → Series
# 提取纳秒属性
Series.dt.nanosecond() → Series
# 返回给定时间的时间戳,time_unit 表示时间戳单位
Series.dt.timestamp(time_unit: TimeUnit = 'us') → Series
# 判断年份是否为闰年
Series.dt.is_leap_year() → Series

# Series的最大时间,返回一个标量
Series.dt.max() → dt.date | dt.datetime | dt.timedelta | None
# Series的最小时间,返回一个标量
Series.dt.min() → dt.date | dt.datetime | dt.timedelta | None
# 平均时间
Series.dt.mean() → dt.date | dt.datetime | None
# 中位数时间
Series.dt.mean() → dt.date | dt.datetime | None

# 重置日期到每月的第一天(其他不变)
Series.dt.month_start() → Series
# 重置日期到每月的最后一天(其他不变)
Series.dt.month_end() → Series

# 对时间加减,by形式参考注1
Series.dt.offset_by(by: str | Expr) → Series

# 格式化时间
Series.dt.strftime(format: str) → Series
Series.dt.to_string(format: str) → Series

# 从 Duration 类型中解析总天数
Series.dt.total_days() → Series

from datetime import datetime
date = pl.datetime_range(
    datetime(2020, 3, 1), datetime(2020, 5, 1), "1mo", eager=True
).alias("datetime")
date.diff().dt.total_days()
# 下面同上
Series.dt.total_hours() → Series
Series.dt.total_microseconds() → Series
Series.dt.total_milliseconds() → Series
Series.dt.total_minutes() → Series
Series.dt.total_nanoseconds() → Series
Series.dt.total_seconds() → Series

注1:Series.dt.offset_by,by参数形式,以下格式字符串

  • 1ns (1 nanosecond)
  • 1us (1 microsecond)
  • 1ms (1 millisecond)
  • 1s (1 second)
  • 1m (1 minute)
  • 1h (1 hour)
  • 1d (1 calendar day)
  • 1w (1 calendar week)
  • 1mo (1 calendar month)
  • 1q (1 calendar quarter)
  • 1y (1 calendar year)
  • 1i (1 index count)
  • 10
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值