1531 字
8 分钟
阅读量加载中...
polars学习-09_数据框关联与拼接

背景#

polars学习系列文章,第9篇 数据框关联与拼接(Join 、Concat)

该系列文章会分享到github,大家可以去下载jupyter文件,进行参考学习

仓库地址:https://github.com/DataShare-duo/polars_learn

小编运行环境#

import sys
print('python 版本:',sys.version.split('|')[0])
#python 版本: 3.11.9
import polars as pl
print("polars 版本:",pl.__version__)
#polars 版本: 1.2.1

数据框关联 Join#

polars 通过指定参数 how,支持以下方式的关联:

  • inner:类似sql中的 inner join,取2个数据框共同的部分
  • left:类似sql中的 left join,取左边数据框所有数据,匹配右边数据框数据,能匹配到的进行匹配,匹配不到的用 null 填充
  • full:类似sql中的 full outer join,返回2个数据框的全量数据,匹配不到的用 null 填充
  • cross:2个数据框的笛卡尔积,数据行数为,len(A) × len(B)
  • semi:用的相对比较少,左边数据框中关联字段同时存在右边数据框中,只返回左边数据框的行,有点类似 inner join,但是不全完一样,即使右边数据框有多行的,左边返回的还是单行,也就是遇到关联字段存在于右边数据框,就返回
  • anti:用的相对比较少,返回左边数据框中关联字段不存在右边数据框中的行,与 semi 相反

数据准备#

df_customers = pl.DataFrame(
{
"customer_id": [1, 2, 3],
"name": ["Alice", "Bob", "Charlie"],
}
)
print(df_customers)
#shape: (3, 2)
┌─────────────┬─────────┐
│ customer_id ┆ name │
------
│ i64 ┆ str
╞═════════════╪═════════╡
1 ┆ Alice │
2 ┆ Bob │
3 ┆ Charlie │
└─────────────┴─────────┘
df_orders = pl.DataFrame(
{
"order_id": ["a", "b", "c"],
"customer_id": [1, 2, 2],
"amount": [100, 200, 300],
}
)
print(df_orders)
#shape: (3, 3)
┌──────────┬─────────────┬────────┐
│ order_id ┆ customer_id ┆ amount │
---------
str ┆ i64 ┆ i64 │
╞══════════╪═════════════╪════════╡
│ a ┆ 1100
│ b ┆ 2200
│ c ┆ 2300
└──────────┴─────────────┴────────┘

Inner join#

df_inner_customer_join = df_customers.join(df_orders,
on="customer_id",
how="inner")
print(df_inner_customer_join)
#shape: (3, 4)
┌─────────────┬───────┬──────────┬────────┐
│ customer_id ┆ name ┆ order_id ┆ amount │
------------
│ i64 ┆ strstr ┆ i64 │
╞═════════════╪═══════╪══════════╪════════╡
1 ┆ Alice ┆ a ┆ 100
2 ┆ Bob ┆ b ┆ 200
2 ┆ Bob ┆ c ┆ 300
└─────────────┴───────┴──────────┴────────┘

Left join#

df_left_join = df_customers.join(df_orders,
on="customer_id",
how="left")
print(df_left_join)
#shape: (4, 4)
┌─────────────┬─────────┬──────────┬────────┐
│ customer_id ┆ name ┆ order_id ┆ amount │
------------
│ i64 ┆ strstr ┆ i64 │
╞═════════════╪═════════╪══════════╪════════╡
1 ┆ Alice ┆ a ┆ 100
2 ┆ Bob ┆ b ┆ 200
2 ┆ Bob ┆ c ┆ 300
3 ┆ Charlie ┆ null ┆ null │
└─────────────┴─────────┴──────────┴────────┘

Outer join#

df_outer_join = df_customers.join(df_orders,
on="customer_id",
how="full")
print(df_outer_join)
#shape: (4, 5)
┌─────────────┬─────────┬──────────┬───────────────────┬────────┐
│ customer_id ┆ name ┆ order_id ┆ customer_id_right ┆ amount │
---------------
│ i64 ┆ strstr ┆ i64 ┆ i64 │
╞═════════════╪═════════╪══════════╪═══════════════════╪════════╡
1 ┆ Alice ┆ a ┆ 1100
2 ┆ Bob ┆ b ┆ 2200
2 ┆ Bob ┆ c ┆ 2300
3 ┆ Charlie ┆ null ┆ null ┆ null │
└─────────────┴─────────┴──────────┴───────────────────┴────────┘

Cross join#

df_colors = pl.DataFrame(
{
"color": ["red", "blue", "green"],
}
)
print(df_colors)
#shape: (3, 1)
┌───────┐
│ color │
---
str
╞═══════╡
│ red │
│ blue │
│ green │
└───────┘
df_sizes = pl.DataFrame(
{
"size": ["S", "M", "L"],
}
)
#print(df_sizes)
df_cross_join = df_colors.join(df_sizes,
how="cross")
print(df_cross_join)
#shape: (9, 2)
┌───────┬──────┐
│ color ┆ size │
------
strstr
╞═══════╪══════╡
│ red ┆ S │
│ red ┆ M │
│ red ┆ L │
│ blue ┆ S │
│ blue ┆ M │
│ blue ┆ L │
│ green ┆ S │
│ green ┆ M │
│ green ┆ L │
└───────┴──────┘

Semi join#

df_cars = pl.DataFrame(
{
"id": ["a", "b", "c"],
"make": ["ford", "toyota", "bmw"],
}
)
print(df_cars)
shape: (3, 2)
┌─────┬────────┐
id ┆ make │
------
strstr
╞═════╪════════╡
│ a ┆ ford │
│ b ┆ toyota │
│ c ┆ bmw │
└─────┴────────┘
df_repairs = pl.DataFrame(
{
"id": ["c", "c"],
"cost": [100, 200],
}
)
print(df_repairs)
#shape: (2, 2)
┌─────┬──────┐
id ┆ cost │
------
str ┆ i64 │
╞═════╪══════╡
│ c ┆ 100
│ c ┆ 200
└─────┴──────┘
df_semi_join = df_cars.join(df_repairs,
on="id",
how="semi")
print(df_semi_join)
#shape: (1, 2)
┌─────┬──────┐
id ┆ make │
------
strstr
╞═════╪══════╡
│ c ┆ bmw │
└─────┴──────┘

Anti join#

df_anti_join = df_cars.join(df_repairs,
on="id",
how="anti")
print(df_anti_join)
#shape: (2, 2)
┌─────┬────────┐
id ┆ make │
------
strstr
╞═════╪════════╡
│ a ┆ ford │
│ b ┆ toyota │
└─────┴────────┘

数据框拼接 Concat#

有以下3种方式的数据框拼接:

  • 纵向拼接/垂直拼接:2个数据框有相同的字段,拼接后产生更长的数据框
  • 横向拼接/水平拼接:2个数据框没有重叠的字段,拼接后产生更宽的数据框
  • 对角拼接:2个数据框有不同的行与列,既有重叠的字段,也有非重叠的字段,拼接后产生即长又宽的数据框

纵向拼接/垂直拼接 Vertical concatenation#

当没有相同的列字段时,纵向拼接会失败

df_v1 = pl.DataFrame(
{
"a": [1],
"b": [3],
}
)
df_v2 = pl.DataFrame(
{
"a": [2],
"b": [4],
}
)
df_vertical_concat = pl.concat(
[
df_v1,
df_v2,
],
how="vertical",
)
print(df_vertical_concat)
#shape: (2, 2)
┌─────┬─────┐
│ a ┆ b │
------
│ i64 ┆ i64 │
╞═════╪═════╡
13
24
└─────┴─────┘

横向拼接/水平拼接 Horizontal concatenation#

当2个数据框有不同的行数时,拼接后短的行会用 null 进行填充

df_h1 = pl.DataFrame(
{
"l1": [1, 2],
"l2": [3, 4],
}
)
df_h2 = pl.DataFrame(
{
"r1": [5, 6],
"r2": [7, 8],
"r3": [9, 10],
}
)
df_horizontal_concat = pl.concat(
[
df_h1,
df_h2,
],
how="horizontal",
)
print(df_horizontal_concat)
#shape: (2, 5)
┌─────┬─────┬─────┬─────┬─────┐
│ l1 ┆ l2 ┆ r1 ┆ r2 ┆ r3 │
---------------
│ i64 ┆ i64 ┆ i64 ┆ i64 ┆ i64 │
╞═════╪═════╪═════╪═════╪═════╡
13579
246810
└─────┴─────┴─────┴─────┴─────┘

对角拼接 Diagonal concatenation#

df_d1 = pl.DataFrame(
{
"a": [1],
"b": [3],
}
)
df_d2 = pl.DataFrame(
{
"a": [2],
"d": [4],
}
)
df_diagonal_concat = pl.concat(
[
df_d1,
df_d2,
],
how="diagonal",
)
print(df_diagonal_concat)
#shape: (2, 3)
┌─────┬──────┬──────┐
│ a ┆ b ┆ d │
---------
│ i64 ┆ i64 ┆ i64 │
╞═════╪══════╪══════╡
13 ┆ null │
2 ┆ null ┆ 4
└─────┴──────┴──────┘

历史相关文章#


以上是自己实践中遇到的一些问题,分享出来供大家参考学习,欢迎关注微信公众号:DataShare ,不定期分享干货

微信公众号 QQ群