연결

연결 (Concatenation)

여러 개의 데이터프레임을 이어 붙이는 방법은 상황에 따라 여러 가지가 있어요. 칼럼이 같은 데이터프레임 두 개는 세로로 붙여 더 긴 데이터프레임을 만들고, 칼럼이 겹치지 않는 두 개는 가로로 붙여 더 넓은 데이터프레임을 만들죠. 이 섹션에서는 Polars의 concat가 제공하는 세 가지 방향 — 세로, 가로, 대각선 — 을 차례로 살펴볼게요.

출처: 공식문서

세로 연결 (Vertical concatenation) - 더 길어지기

세로 연결(vertical concatenation)은 DataFrames 리스트의 모든 행을 하나의 더 긴 DataFrame으로 결합해요.

import polars as pl

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 │
╞═════╪═════╡
│ 1   ┆ 3   │
│ 2   ┆ 4   │
└─────┴─────┘

세로 연결은 데이터프레임들이 같은 칼럼 이름을 가지지 않으면 실패합니다.

가로 연결 (Horizontal concatenation) - 더 넓어지기

가로 연결(horizontal concatenation)은 DataFrames 리스트의 모든 칼럼을 하나의 더 넓은 DataFrame으로 결합해요.

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 │
╞═════╪═════╪═════╪═════╪═════╡
│ 1   ┆ 3   ┆ 5   ┆ 7   ┆ 9   │
│ 2   ┆ 4   ┆ 6   ┆ 8   ┆ 10  │
└─────┴─────┴─────┴─────┴─────┘

가로 연결은 데이터프레임들이 겹치는 칼럼을 가지면 실패하고, 또 두 데이터프레임의 높이(행 수)가 같아야 합니다. 높이가 다른 데이터프레임을 결합하려면 how="horizontal_extend"를 쓰세요. 이 모드는 더 짧은 칼럼의 끝을 null 값으로 채워서 가장 긴 데이터프레임의 높이에 맞춥니다.

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

대각선 연결 (Diagonal concatenation) - 더 길어지고, 더 넓어지고, 더 null 많아지기

대각선 연결(diagonal concatenation)은 DataFrames 리스트의 모든 행과 칼럼을 하나의 더 길고/더 넓은 DataFrame으로 결합해요.

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  │
╞═════╪══════╪══════╡
│ 1   ┆ 3    ┆ null │
│ 2   ┆ null ┆ 4    │
└─────┴──────┴──────┘

대각선 연결은 칼럼 이름이 겹치지 않을 때 null을 생성합니다.

데이터프레임의 형태가 맞지 않으면서 겹치는 의미적 키(semantic key)가 있다면, 연결 대신 데이터프레임을 조인할 수 있어요.

리청킹 (Rechunking)

연결 전에 우리에겐 df1df2 두 데이터프레임이 있어요. df1df2의 각 칼럼은 메모리에서 하나 이상의 청크(chunk)에 들어 있죠. 기본적으로 연결 중에는 각 칼럼의 청크들이 연속되게(contiguous) 만들어지지 않습니다. 이렇게 하면 연결 연산이 더 빠르고 메모리를 덜 쓰지만, 데이터가 연속 메모리에 있을 때 이점을 얻는 이후 연산은 느려질 수 있어요. 분산된(fragmented) 청크들을 하나의 새 청크로 복사하는 과정을 **리청킹(rechunking)**이라고 합니다. 리청킹은 비용이 큰 연산이에요. 버전 0.20.26 이전에는 리청킹이 기본이었지만, 새 버전에서는 기본적으로 수행하지 않습니다. 연결된 DataFrame을 Polars가 리청킹하길 원한다면 연결 시 rechunk = True를 지정하세요.

더 알아보기 (Learn more)

  • 데이터프레임을 행·칼럼 기준으로 접합하는 대신 키 값을 기준으로 결합하고 싶다면 조인 문서를 참고하세요.