Post

pandas和polars

pandas和polars

本来想记录一些基本用法的,但是发现官方文档已经够详细了,再记录就有点多余了。觉着更关键的还是多使用,熟能生巧。不用就忘,这是必不可免的。所以,总结一句话,那就是多写代码

那这篇文章要做什么呢,我也在思考,不如先做个总结和对比吧。

(以下介绍均来自深度求索

pandas介绍

诞生于2008年,是 Python 数据科学生态的核心工具之一

  • 底层使用 NumPy 数组,支持丰富的数值计算和向量化操作
  • 适合中小规模数据(GB级别以内)
  • 支持数据清洗、聚合、时间序列、合并、可视化等操作

局限:

  • 默认单线程运行,处理大数据时效率较低;
  • 操作时可能产生数据副本,内存利用率不够高效

官方文档:pandas documentation

polars介绍

用 Rust 编写,支持多线程和查询优化,速度比 Pandas 快数倍甚至数十倍

  • 采用 Apache Arrow 内存格式,减少不必要的内存复制
  • 通过 lazy() 模式优化执行计划,提升复杂查询效率
  • 能处理远超内存大小的数据集(通过流式处理)

官方文档:Index - Polars user guide
API文档:Python API reference — Polars documentation

polars

创建数据帧

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import polars as pl
import datetime as dt

df = pl.DataFrame({
    'name': ['Alice Archer', 'Bob Brown', 'Charlie Cooper', 'David Donovan'],
    'birthdate': [
        dt.date(1990, 1, 1),
        dt.date(1985, 5, 15),
        dt.date(2000, 12, 31),
        dt.date(1995, 7, 20)
    ],
    'weight': [55.5, 70.2, 65.0, 80.1],
    'height': [1.65, 1.80, 1.75, 1.90],
})

数据查看

1
2
3
4
5
6
df.head()       # 前5行
df.tail(3)      # 后3行
df.shape        # (行数,列数)
df.columns      # 列名
df.schema       # 列名和数据类型
df.describe()   # 统计描述

数据选择

选择列

1
2
3
4
5
df['name', 'weight']

df.select(["name", 'weight'])

df.select(pl.col('name', 'weight'))

选择行

1
2
df[0]
df[1:3]

条件选择

1
2
3
4
5
6
7
8
9
df.filter(
    pl.col('weight') > 60 &
    (pl.col('height')).is_in([1.75, 1.90])
)
"""
与:&
或:|
非:~
"""

数据操作

添加列

1
2
3
4
5
6
df = df.with_columns(
    pl.Series("salary", [5000, 6000, 7000, 4000]),
    (dt.date.today().year - pl.col('birthdate').dt.year()).alias('age'),
    bmi=pl.col('weight') / (pl.col('height') ** 2),
    is_adult=pl.lit(True),
)

删除列

1
df = df.drop('salary')

列重命名

1
df.rename({'old_name': 'new_name'})

排列

1
df.sort('age', descending=True)

分组聚合

1
2
3
4
5
6
7
df.group_by(
    decade=pl.col('birthdate').dt.year() // 10 * 10
).agg(
    pl.len().alias('sample_size'),
    pl.col('weight').mean().alias('avg_weight'),
    pl.col('height').max().alias('tallest'),
)

合并

连接

1
2
3
4
5
6
7
df2 = pl.DataFrame({
    "name": ["Bob Brown", "David Donovan", "Alice Archer", 'Eliy Smith'],
    "has_kid": [True, False, False, False],
    "siblings": [1, 2, 4, 6],
})

joined = df.join(df2, on='name', how='left').sort('name')

垂直合并

1
2
3
4
5
6
7
8
9
10
11
12
13
df3 = pl.DataFrame({
    "name": ["Ethan Edwards", "Fiona Foster", "Grace Gibson", "Henry Harris"],
    "birthdate": [
        dt.date(1977, 5, 10),
        dt.date(1975, 6, 23),
        dt.date(1973, 7, 22),
        dt.date(1971, 8, 3),
    ],
    "weight": [67.9, 72.5, 57.6, 93.1],
    "height": [1.76, 1.6, 1.66, 1.8],
})

results = pl.concat([df, df3], how='vertical').sort('name')

处理缺失值

1
2
3
4
5
6
7
8
# 检查缺失值
df.null_count()

# 删除包含缺失值的行
df.drop_nulls()

# 填充缺失值
df.fill_null(0)

应用函数

1
df.select(pl.col('age').map_elements(lambda x: x + 1))

数据输入/输出

读取数据

1
2
3
pl.read_csv('file.csv')

pl.read_parquet('file.parquet')

写入数据

1
2
df.write_csv('output.csv')
df.write_parquet('output.parquet')

数据帧转换

polars和pandas相互转换

使用的都是polars的方法

1
2
3
pd_df = pl_df.to_pandas()

pl_df = pl.from_pandas(pd_df)

转换成字典

1
2
3
df.to_dicts()

df.rows(named=True) 

pandas

创建数据帧

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import pandas as pd
import datetime as dt

df = pd.DataFrame({
    'name': ['Alice Archer', 'Bob Brown', 'Charlie Cooper', 'David Donovan'],
    'birthdate': [
        dt.date(1990, 1, 1),
        dt.date(1985, 5, 15),
        dt.date(2000, 12, 31),
        dt.date(1995, 7, 20)
    ],
    'weight': [55.5, 70.2, 65.0, 80.1],
    'height': [1.65, 1.80, 1.75, 1.90],
})

数据选择

选择列

1
2
3
df['name']

df[['name', 'weight']]

选择行

基于位置

1
2
3
4
5
6
7
8
9
# 返回series
df.iloc[0]

# 返回dataframe
df.iloc[[0, 2, 3]]  
df.iloc[0:3]

# 选择元素
df.iloc[2, 0]  # 返回'Charlie Cooper'

基于标签

1

条件选择

1
2
df[df['age'] > 20]
df[(df['age'] > 20) & (df['weight'] > 60)]

数据操作

添加列

1
df['salary'] = [5000, 6000, 7000, 4000]

删除列

1
df.drop('salary', axis=1, inplace=True)

排序

1
df.sort_values('age', ascending=False)

分组聚合

1
df.groupby('age')['weight'].mean()

处理缺失值

1
2
3
df.isnull()       # 检查缺失值
df.dropna()       # 删除包含缺失值的行
df.fillna(value)  # 填充缺失值

合并

连接

1
pd.merge(df1, df2, on='key_column')

垂直合并

1
pd.concat([df1, df2])

数据帧转换

转化成字典

1
df.to_dict("records")
This post is licensed under CC BY 4.0 by the author.