对比 Python 的 Polars 与 R 的 dplyr 常用函数与语法。
帮助从 R 转向 Python 的分析师快速掌握 Polars。
| 项目 | Polars(Python) | dplyr(R) |
|---|
| 数据结构 | pl.DataFrame / pl.LazyFrame | tibble |
| 求值方式 | 惰性或即时 | 即时 |
| 表达式风格 | pl.col("x") + 1 | mutate(x = x + 1) |
| 管道 | 方法链或 ` | ` |
| 性能 | 多线程 + Rust 内核 | 单线程(可结合 data.table) |
| SQL 支持 | pl.SQLContext | dbplyr(翻译 SQL) |
| 功能 | dplyr / R 语法 | Polars 语法 |
|---|
| 读取 CSV | read.csv("file.csv") | pl.read_csv("file.csv") |
| 查看前几行 | head(df, 5) | df.head(5) |
| 查看后几行 | tail(df, 5) | df.tail(5) |
| 查看列名 | colnames(df) | df.columns |
| 查看维度 | dim(df) | df.shape |
| 取列 | df$col | df["col"] or df.select("col") |
| 转为 pandas | N/A | df.to_pandas() |
| 打印概要 | glimpse(df) | df.describe() |
| 操作 | dplyr | Polars |
|---|
| 选择列 | select(df, col1, col2) | df.select(["col1", "col2"]) |
| 排除列 | select(df, -col1) | df.select(pl.exclude("col1")) |
| 重命名列 | rename(df, new = old) | df.rename({"old": "new"}) |
| 筛选行 | filter(df, x > 10) | df.filter(pl.col("x") > 10) |
| 多条件筛选 | filter(df, x > 10 & y == "A") | df.filter((pl.col("x") > 10) & (pl.col("y") == "A")) |
| 排序 | arrange(df, x) | df.sort("x") |
| 降序排序 | arrange(df, desc(x)) | df.sort("x", descending=True) |
| 取样 | sample_n(df, 100) | df.sample(n=100) |
| 去重 | distinct(df) | df.unique() |
| 去重(按列) | distinct(df, col1, col2) | df.unique(subset=["col1", "col2"]) |
| 功能 | dplyr | Polars |
|---|
| 新增列 | mutate(df, z = x + y) | df.with_columns((pl.col("x") + pl.col("y")).alias("z")) |
| 修改列 | mutate(df, x = x * 2) | df.with_columns((pl.col("x") * 2).alias("x")) |
| 多列变换 | mutate(across(starts_with("x"), log)) | df.with_columns(pl.col("^x.*$").log()) |
| 条件赋值 | mutate(df, flag = if_else(x > 0, 1, 0)) | df.with_columns(pl.when(pl.col("x") > 0).then(1).otherwise(0).alias("flag")) |
| 替换缺失 | mutate(df, x = if_else(is.na(x), 0, x)) | df.with_columns(pl.col("x").fill_null(0)) |
| 缺失处理 | filter(!is.na(x)) | df.drop_nulls(["x"]) |
| 替换值 | mutate(df, x = recode(x, a=1, b=2)) | df.with_columns(pl.col("x").replace({"a":1, "b":2})) |
| 类型转换 | mutate(df, x = as.numeric(x)) | df.with_columns(pl.col("x").cast(pl.Float64)) |
| 操作 | dplyr | Polars |
|---|
| 分组 | group_by(df, g) | df.group_by("g") |
| 汇总 | summarise(df, mean_x = mean(x)) | df.select(pl.col("x").mean().alias("mean_x")) |
| 分组汇总 | summarise(group_by(df, g), mean_x = mean(x)) | df.group_by("g").agg(pl.col("x").mean().alias("mean_x")) |
| 多列聚合 | summarise(df, across(c(a, b), mean)) | df.select(pl.col(["a","b"]).mean()) |
| 计数 | count(df, g) | df.group_by("g").len() |
| 组内排序取前几 | slice_max(order_by = x, n = 1) | df.sort("x").group_by("g").head(1) |
| 类型 | dplyr | Polars |
|---|
| 内连接 | inner_join(df1, df2, by="id") | df1.join(df2, on="id", how="inner") |
| 左连接 | left_join(df1, df2, by="id") | df1.join(df2, on="id", how="left") |
| 右连接 | right_join(df1, df2, by="id") | df1.join(df2, on="id", how="right") |
| 全连接 | full_join(df1, df2, by="id") | df1.join(df2, on="id", how="outer") |
| 半连接 | semi_join(df1, df2, by="id") | df1.join(df2, on="id", how="semi") |
| 反连接 | anti_join(df1, df2, by="id") | df1.join(df2, on="id", how="anti") |
| 纵向合并 | bind_rows(df1, df2) | pl.concat([df1, df2]) |
| 横向合并 | bind_cols(df1, df2) | pl.concat([df1, df2], how="horizontal") |
| 操作 | dplyr / tidyr | Polars |
|---|
| 转宽表 | pivot_wider(df, names_from=cat, values_from=val) | df.pivot(values="val", index="id", columns="cat") |
| 转长表 | pivot_longer(df, cols=c(a,b)) | df.melt(id_vars="id", value_vars=["a","b"]) |
| 堆叠 | bind_rows(df1, df2) | pl.concat([df1, df2]) |
| 展平列表列 | unnest(df, col) | df.explode("col") |
| 功能 | dplyr | Polars |
|---|
| 分组内排名 | mutate(rank = rank(x)) | df.with_columns(pl.col("x").rank().over("g")) |
| 滚动均值 | mutate(ma = rollmean(x, 3)) | df.with_columns(pl.col("x").rolling_mean(3)) |
| 滚动和 | mutate(sum3 = rollsum(x, 3)) | df.with_columns(pl.col("x").rolling_sum(3)) |
| 累积和 | mutate(cumsum = cumsum(x)) | df.with_columns(pl.col("x").cum_sum()) |
| 累积均值 | mutate(cummean = cummean(x)) | df.with_columns(pl.col("x").cum_mean()) |
| 操作 | stringr / dplyr | Polars |
|---|
| 小写 | mutate(x = str_to_lower(x)) | df.with_columns(pl.col("x").str.to_lowercase()) |
| 大写 | mutate(x = str_to_upper(x)) | df.with_columns(pl.col("x").str.to_uppercase()) |
| 子串提取 | str_sub(x, 1, 3) | pl.col("x").str.slice(0, 3) |
| 字符长度 | str_length(x) | pl.col("x").str.len_bytes() |
| 模式匹配 | filter(str_detect(x, "A")) | df.filter(pl.col("x").str.contains("A")) |
| 字符替换 | mutate(x = str_replace(x, "A", "B")) | pl.col("x").str.replace("A", "B") |
| 分割 | separate(df, x, into=c("a","b"), sep="-") | pl.col("x").str.split("-") + df.explode() |
| 操作 | dplyr / lubridate | Polars |
|---|
| 转日期 | as_date(x) | pl.col("x").str.strptime(pl.Date, "%Y-%m-%d") |
| 提取年 | year(x) | pl.col("x").dt.year() |
| 提取月 | month(x) | pl.col("x").dt.month() |
| 提取日 | day(x) | pl.col("x").dt.day() |
| 提取星期 | wday(x) | pl.col("x").dt.weekday() |
| 提取小时 | hour(x) | pl.col("x").dt.hour() |
| 加减日期 | x + days(5) | pl.col("x") + pl.duration(days=5) |
| 时间差 | difftime(x, y) | (pl.col("x") - pl.col("y")) |
filter(category == "A") %>%
summarise(mean_val = mean(value, na.rm = TRUE),