代码之家  ›  专栏  ›  技术社区  ›  Eir Nym

Polars:设置另一行中缺少的值

  •  2
  • Eir Nym  · 技术社区  · 1 年前

    以下数据帧表示基本的扁平树结构,如下所示,其中成对 (id, sub-id) (sub-id, key) 总是独一无二的 key 在相同的情况下总是代表相同的东西 id

    id1
    └─┬─ sub-id 
    │ │   └─── key1
    │ │        └─── value
    │ └─ sub-id2 
    │     └─── key1
    │          └─── None
    id2
    └─── sub-id3 
          └─── key2
               └─── value
    

    不需要图形表示,以下是定义 polars.DataFrame

    df = pl.DataFrame(
        {
            "id": [1, 1, 2, 2, 2, 3],
            "sub-id": [1, 1, 2, 3, 3, 4],
            "key": ["key_1_1", "key_1_2", "key_2_1", "key_2_1", "key_2_2", "key_3"],
            "value": ["value1 1", "value 1 2", None, "value 2 1", "value 2 2", "value 3"],
        }
    )
    

    表表示中的相同数据帧:

    shape: (6, 4)
    
    ┌────┬────────┬─────────┬───────────┐
    │ ID │ sub-id │ key     │ value     │
    ╞════╪════════╪═════════╪═══════════╡
    │ 1  │ 1      │ key_1_1 │ value 1   │
    │ 1  │ 1      │ key_1_2 │ value 2   │
    │ 2  │ 2      │ key_2_1 │ value 2 1 │
    │ 2  │ 3      │ key_2_1 │ None      │
    │ 2  │ 3      │ key_2_2 │ value 2 2 │
    │ 3  │ 4      │ key_3   │ value 3   │
    └────┴────────┴─────────┴───────────┘
    

    我该如何使用以下方式填补空白 polars 数据的总大小约为100k行。

    shape: (6, 4)
    
    ┌────┬────────┬─────────┬───────────┐
    │ ID │ sub-id │ key     │ value     │
    ╞════╪════════╪═════════╪═══════════╡
    │ 1  │ 1      │ key_1_1 │ value 1   │
    │ 1  │ 1      │ key_1_2 │ value 2   │
    │ 2  │ 2      │ key_2_1 │ value 2 1 │
    │ 2  │ 3      │ key_2_1 │ value 2 1 │
    │ 2  │ 3      │ key_2_2 │ value 2 2 │
    │ 3  │ 4      │ key_3   │ value 3   │
    └────┴────────┴─────────┴───────────┘
    
    2 回复  |  直到 1 年前
        1
  •  2
  •   Hericks    1 年前

    pl.Expr.fill_null 以填充缺失的值。

    作为填充值,我们使用第一个具有相同值的非空值 id key 。因为我们假设所有值都相同 身份证件 钥匙 都是一样的,取第一个值是合理的。其结构如下:

    df.with_columns(
        pl.col("value").fill_null(
            pl.col("value").filter(pl.col("value").is_not_null()).first().over("id", "key")
        )
    )
    
    shape: (6, 4)
    ┌─────┬────────┬─────────┬───────────┐
    │ id  ┆ sub-id ┆ key     ┆ value     │
    │ --- ┆ ---    ┆ ---     ┆ ---       │
    │ i64 ┆ i64    ┆ str     ┆ str       │
    ╞═════╪════════╪═════════╪═══════════╡
    │ 1   ┆ 1      ┆ key_1_1 ┆ value 1   │
    │ 1   ┆ 1      ┆ key_1_2 ┆ value 2   │
    │ 2   ┆ 2      ┆ key_2_1 ┆ value 2 1 │
    │ 2   ┆ 3      ┆ key_2_1 ┆ value 2 1 │
    │ 2   ┆ 3      ┆ key_2_2 ┆ value 2 2 │
    │ 3   ┆ 4      ┆ key_3   ┆ value 3   │
    └─────┴────────┴─────────┴───────────┘
    

    注意。 我需要稍微调整你的代码,以匹配你在文中描述的示例。

    df = pl.DataFrame({
        "id": [1, 1, 2, 2, 2, 3],
        "sub-id": [1, 1, 2, 3, 3, 4],
        "key": ["key_1_1", "key_1_2", "key_2_1", "key_2_1", "key_2_2", "key_3"],
        "value": ["value 1", "value 2", None, "value 2 1", "value 2 2", "value 3"],
    })
    
        2
  •  1
  •   Derek Roberts    1 年前

    通过执行以下操作可以帮助您实现这一目标 forward fill operation 基于两者 id key 它确保了相同范围内的缺失值 身份证件 钥匙 组中填充了最新的非空值

    使用 with_columns 使其能够使用 forward_fill 操作

    进一步澄清:

    1. pl.col("value") :这将从DataFrame中选择值列。 forward_fill():此方法用指定上下文中最后一个已知的非空值填充任何None值。

    2. over(["id", "key"]): 这将确保填充操作尊重两者的分组 身份证件 钥匙 . 换句话说,填充操作只发生在每个id和键组内,因此来自不同组的值不会相互干扰。

    我提供了一个代码片段来指导你。。。

    import polars as pl
    
    # Define the DataFrame
    df = pl.DataFrame(
        {
            "ID": [1, 1, 2, 2, 2, 3],
            "sub-id": [1, 1, 2, 3, 3, 4],
            "key": ["key_1_1", "key_1_2", "key_2_1", "key_2_1", "key_2_2", "key_3"],
            "value": ["value 1", "value 2", "value 2 1", None, "value 2 2", "value 3"],
        }
    )
    
    # Perform the fill operation
    filled_df = df.with_columns(pl.col("value").forward_fill().over(["ID", "key"]))
    
    # Display the result
    print(filled_df)
    

    结果:

    shape: (6, 4)
    ┌─────┬────────┬─────────┬───────────┐
    │ ID  ┆ sub-id ┆ key     ┆ value     │
    │ --- ┆ ---    ┆ ---     ┆ ---       │
    │ i64 ┆ i64    ┆ str     ┆ str       │
    ╞═════╪════════╪═════════╪═══════════╡
    │ 1   ┆ 1      ┆ key_1_1 ┆ value 1   │
    │ 1   ┆ 1      ┆ key_1_2 ┆ value 2   │
    │ 2   ┆ 2      ┆ key_2_1 ┆ value 2 1 │
    │ 2   ┆ 3      ┆ key_2_1 ┆ value 2 1 │
    │ 2   ┆ 3      ┆ key_2_2 ┆ value 2 2 │
    │ 3   ┆ 4      ┆ key_3   ┆ value 3   │
    └─────┴────────┴─────────┴───────────┘
    

    或者

    您可以使用 join 为了实现这一点,也可以将非空df与之前的原始df连接起来。

    下面是一个代码片段

    import polars as pl
    
    # Define the DataFrame
    df = pl.DataFrame(
        {
            "ID": [1, 1, 2, 2, 2, 3],
            "sub-id": [1, 1, 2, 3, 3, 4],
            "key": ["key_1_1", "key_1_2", "key_2_1", "key_2_1", "key_2_2", "key_3"],
            "value": ["value 1", "value 2", "value 2 1", None, "value 2 2", "value 3"],
        }
    )
    
    # Separate the non-null values
    non_null_df = df.filter(pl.col("value").is_not_null())
    
    # Join the original DataFrame with the non-null DataFrame
    new_table_joined_df = df.join(non_null_df, on=["ID", "key"], how="left", suffix="_filled")
    
    # Fill the original `value` column with the joined `value_filled` column
    filled_df = new_table_joined_df.with_columns(pl.col("value").fill_null(pl.col("value_filled"))).select(df.columns)
    
    # Display the result
    print(filled_df)