【问题标题】:Python - How can I aggregate a pandas dataframe base on conditions on different rows?Python - 如何根据不同行的条件聚合 pandas 数据框?
【发布时间】:2022-11-26 13:31:34
【问题描述】:

我有一个包含路段信息的熊猫数据框。

PRIRTECODE PRIM_BMP PRIM_EMP SEGMENT_LENGTH ELEMENT_ID RAMP CURVE_YEAR SEGMENT_TYPE
0001A 0 0.147 0.147 4850943 0 2019 Line
0001A 0.147 0.183 0.036 4850943 0 2019 Line
0001A 0.183 0.24 0.057 4850943 0 2019 Arc left
0001A 0.24 0.251 0.011 4850945 0 2019 Arc left
0001A 0.251 0.27 0.019 4850945 0 2019 Arc left
0001A 0.27 0.295 0.025 4048920 0 2019 Arc left
0001A 0.295 0.31 0.015 4048920 0 2019 Line
0001A 0.31 0.36 0.05 4048921 0 2019 Line
0001A 0.36 0.363 0.003 4048779 0 2019 Line
0001A 0.363 0.437 0.074 4048779 0 2019 Arc left
0001A 0.437 0.483 0.046 4048779 0 2019 Arc right
0001A 0.483 0.568 0.085 4048779 0 2019 Arc right
0001A 0.568 0.6 0.032 4048779 0 2019 Line

我需要根据与 SEGMENT TYPE 相似的特征进行聚合,并对 SEGMENT_LENGTH 求和。我可以用 pandas group_by 做到这一点。但是,我需要确保要聚合的段是连续的。为此,我需要查看以下变量:

  • PRIM_BMP:路段开始的英里数。
  • PRIM_EMP:路段结束的英里数。

因此,如果一个段的 PRIM_EMP 等于第二个段的 PRIM_BMP,则两个段是连续的。另外,我需要保留第一段的 PRIM_BMP 和最后一段的 PRIM_EMP。

最终结果应如下所示:

PRIRTECODE PRIM_BMP PRIM_EMP SEGMENT_LENGTH RAMP CURVE_YEAR SEGMENT_TYPE
0001A 0 0.183 0.183 0 2019 Line
0001A 0.183 0.295 0.112 0 2019 Arc left
0001A 0.295 0.363 0.068 0 2019 Line
0001A 0.363 0.568 0.205 0 2019 Arc right
0001A 0.568 0.6 0.032 0 2019 Line

我已经尝试使用 groupby 使用我需要聚合段的特征,但我还没有找到一种方法来单独聚合连续的段。

【问题讨论】:

    标签: python dataframe group-by aggregation


    【解决方案1】:

    以防万一您用完了选项,这是基于convtools 的解决方案。 (我必须承认——我是作者)。

    from convtools import conversion as c
    from convtools.contrib.tables import Table
    
    
    rows = [
        {'PRIRTECODE': '0001A', 'PRIM_BMP': 0.0, 'PRIM_EMP': 0.147, 'SEGMENT_LENGTH': 0.147, 'ELEMENT_ID': 4850943, 'RAMP': 0, 'CURVE_YEAR': 2019, 'SEGMENT_TYPE': 'Line'},
        {'PRIRTECODE': '0001A', 'PRIM_BMP': 0.147, 'PRIM_EMP': 0.183, 'SEGMENT_LENGTH': 0.036, 'ELEMENT_ID': 4850943, 'RAMP': 0, 'CURVE_YEAR': 2019, 'SEGMENT_TYPE': 'Line'},
        {'PRIRTECODE': '0001A', 'PRIM_BMP': 0.183, 'PRIM_EMP': 0.24, 'SEGMENT_LENGTH': 0.057, 'ELEMENT_ID': 4850943, 'RAMP': 0, 'CURVE_YEAR': 2019, 'SEGMENT_TYPE': 'Arc left'},
        {'PRIRTECODE': '0001A', 'PRIM_BMP': 0.24, 'PRIM_EMP': 0.251, 'SEGMENT_LENGTH': 0.011, 'ELEMENT_ID': 4850945, 'RAMP': 0, 'CURVE_YEAR': 2019, 'SEGMENT_TYPE': 'Arc left'},
        {'PRIRTECODE': '0001A', 'PRIM_BMP': 0.251, 'PRIM_EMP': 0.27, 'SEGMENT_LENGTH': 0.019, 'ELEMENT_ID': 4850945, 'RAMP': 0, 'CURVE_YEAR': 2019, 'SEGMENT_TYPE': 'Arc left'},
        {'PRIRTECODE': '0001A', 'PRIM_BMP': 0.27, 'PRIM_EMP': 0.295, 'SEGMENT_LENGTH': 0.025, 'ELEMENT_ID': 4048920, 'RAMP': 0, 'CURVE_YEAR': 2019, 'SEGMENT_TYPE': 'Arc left'},
        {'PRIRTECODE': '0001A', 'PRIM_BMP': 0.295, 'PRIM_EMP': 0.31, 'SEGMENT_LENGTH': 0.015, 'ELEMENT_ID': 4048920, 'RAMP': 0, 'CURVE_YEAR': 2019, 'SEGMENT_TYPE': 'Line'},
        {'PRIRTECODE': '0001A', 'PRIM_BMP': 0.31, 'PRIM_EMP': 0.36, 'SEGMENT_LENGTH': 0.05, 'ELEMENT_ID': 4048921, 'RAMP': 0, 'CURVE_YEAR': 2019, 'SEGMENT_TYPE': 'Line'},
        {'PRIRTECODE': '0001A', 'PRIM_BMP': 0.36, 'PRIM_EMP': 0.363, 'SEGMENT_LENGTH': 0.003, 'ELEMENT_ID': 4048779, 'RAMP': 0, 'CURVE_YEAR': 2019, 'SEGMENT_TYPE': 'Line'},
        {'PRIRTECODE': '0001A', 'PRIM_BMP': 0.363, 'PRIM_EMP': 0.437, 'SEGMENT_LENGTH': 0.074, 'ELEMENT_ID': 4048779, 'RAMP': 0, 'CURVE_YEAR': 2019, 'SEGMENT_TYPE': 'Arc left'},
        {'PRIRTECODE': '0001A', 'PRIM_BMP': 0.437, 'PRIM_EMP': 0.483, 'SEGMENT_LENGTH': 0.046, 'ELEMENT_ID': 4048779, 'RAMP': 0, 'CURVE_YEAR': 2019, 'SEGMENT_TYPE': 'Arc right'},
        {'PRIRTECODE': '0001A', 'PRIM_BMP': 0.483, 'PRIM_EMP': 0.568, 'SEGMENT_LENGTH': 0.085, 'ELEMENT_ID': 4048779, 'RAMP': 0, 'CURVE_YEAR': 2019, 'SEGMENT_TYPE': 'Arc right'},
        {'PRIRTECODE': '0001A', 'PRIM_BMP': 0.568, 'PRIM_EMP': 0.6, 'SEGMENT_LENGTH': 0.032, 'ELEMENT_ID': 4048779, 'RAMP': 0, 'CURVE_YEAR': 2019, 'SEGMENT_TYPE': 'Line'},
    ]
    
    iterable_of_results = (
        c.chunk_by_condition(
            c.and_(
                c.CHUNK.item(-1, "SEGMENT_TYPE") == c.item("SEGMENT_TYPE"),
                c.CHUNK.item(-1, "PRIM_EMP") == c.item("PRIM_BMP"),
            )
        )
        .aggregate(
            {
                "SEGMENT_TYPE": c.ReduceFuncs.First(c.item("SEGMENT_TYPE")),
                "length": c.ReduceFuncs.Sum(c.item("SEGMENT_LENGTH")),
            }
        )
        # should you want to reuse this conversion multiple times, run
        # .gen_converter() to get a function and store it for further reuse
        .execute(rows)
    )
    
    

    结果:

    In [54]: list(iterable_of_results)
    Out[54]:
    [{'SEGMENT_TYPE': 'Line', 'length': 0.183},
     {'SEGMENT_TYPE': 'Arc left', 'length': 0.11200000000000002},
     {'SEGMENT_TYPE': 'Line', 'length': 0.068},
     {'SEGMENT_TYPE': 'Arc left', 'length': 0.074},
     {'SEGMENT_TYPE': 'Arc right', 'length': 0.131},
     {'SEGMENT_TYPE': 'Line', 'length': 0.032}]
    

    【讨论】:

      猜你喜欢
      • 2020-07-04
      • 2016-05-01
      • 2021-06-01
      • 2021-12-01
      • 2021-06-23
      • 2020-01-14
      • 2023-01-08
      • 2023-03-09
      • 2018-02-02
      相关资源
      最近更新 更多