遍历数据框和递归过滤器

时间:2020-06-28 04:12:35

标签: pyspark databricks

我有2个数据框。 “ MinNRule”和“ SampleData” MinNRule根据需要的SampleData提供一些规则信息:

  1. 在MinNRule.MinimumNPopulation和MinNRule.OrderOfOperation中定义的列上汇总“样本数据”

  2. 检查Aggregate.Entity> = MinNRule.MinimumNValue

    a。对于不符合MinNRule.MinimumNValue的所有实体,从总体中删除

    b。对于所有符合MinNRule.MinimumNValue的实体,保留人口

  3. 使用2.b数据集对下一个MinNRule.OrderOfOperation执行1到2

MinNRule
| MinimumNGroupName | MinimumNPopulation | MinimumNValue | OrderOfOperation |
|:-----------------:|:------------------:|:-------------:|:----------------:|
|       Group1      | People by Facility |       6       |         1        |
|       Group1      |  People by Project |       4       |         2        |

SampleData

| Facility  | Project   | PeopleID  |
|:--------: |:-------:  |:--------: |
|    F1     |    P1     |  166152   |
|    F1     |    P1     |  425906   |
|    F1     |    P1     |  332127   |
|    F1     |    P1     |  241630   |
|    F1     |    P2     |  373865   |
|    F1     |    P2     |  120672   |
|    F1     |    P2     |  369407   |
|    F2     |    P4     |  121705   |
|    F2     |    P4     |  211807   |
|    F2     |    P4     |  408041   |
|    F2     |    P4     |  415579   |

建议步骤:

  1. 读取MinNRule,读取具有OrderOfOperation = 1的规则

    a。通过设施进行分组,依靠人

    b。用1.a聚合SampleData并与MinimumNValue = 6

    比较
        | Facility  | Count     | MinNPass  |
        |:--------: |:-------:  |:--------: |
        |    F1     |    7      |  Y        |
        |    F2     |    4      |  N        | 
  1. 选择MinNPass ='Y'行,并将初始数据帧向下过滤到那些实体(F2被删除)
            | Facility  | Project   | PeopleID  |
            |:--------: |:-------:  |:--------: |
            |    F1     |    P1     |  166152   |
            |    F1     |    P1     |  425906   |
            |    F1     |    P1     |  332127   |
            |    F1     |    P1     |  241630   |
            |    F1     |    P2     |  373865   |
            |    F1     |    P2     |  120672   |
            |    F1     |    P2     |  369407   |
  1. 读取MinNRule,使用OrderOfOperation = 2读取规则

    a。通过项目进行分组,依靠人

    b。通过3.a汇总SampleData并将其与MinimumNValue = 4

    进行比较
        | Project   | Count     | MinNPass  |
        |:--------: |:-------:  |:--------: |
        |    P1     |    4      |  Y        |
        |    P2     |    3      |  N        | 
  1. 选择MinNPass ='Y'行,并在3个数据帧中向下过滤到那些实体(P2被删除)
  2. 打印最终结果
            | Facility  | Project   | PeopleID  |
            |:--------: |:-------:  |:--------: |
            |    F1     |    P1     |  166152   |
            |    F1     |    P1     |  425906   |
            |    F1     |    P1     |  332127   |
            |    F1     |    P1     |  241630   |

想法:

  1. 我一直在考虑将MinNRule移到LocalIterator并循环遍历并“过滤” SampleData
  2. 我不确定如何在一个循环结束时将结果传递给另一个
  3. 仍在学习Pyspark,不确定这是否正确。 我正在使用Azure Databricks

1 个答案:

答案 0 :(得分:1)

IIUC,由于规则df定义了规则,因此它必须很小并且可以收集到驱动程序中以对主数据执行操作。

获得期望结果的一种方法是收集规则df并将其传递给reduce函数,例如:

data = MinNRule.orderBy('OrderOfOperation').collect()

from pyspark.sql.functions import *
from functools import reduce

dfnew = reduce(lambda df, rules: df.groupBy(col(rules.MinimumNPopulation.split('by')[1].strip())).\
       agg(count(col({'People':'PeopleID'}.get(rules.MinimumNPopulation.split('by')[0].strip()))).alias('count')).\
       filter(col('count')>=rules.MinimumNValue).drop('count').join(df,rules.MinimumNPopulation.split('by')[1].strip(),'inner'), data, sampleData)

dfnew.show()

+-------+--------+--------+
|Project|Facility|PeopleID|
+-------+--------+--------+
|     P1|      F1|  166152|
|     P1|      F1|  425906|
|     P1|      F1|  332127|
|     P1|      F1|  241630|
+-------+--------+--------+

或者,您也可以遍历df并获得结果,两种情况下的性能均保持不变

import pyspark.sql.functions as f
mapped_cols = {'People':'PeopleID'}
data = MinNRule.orderBy('OrderOfOperation').collect()
for i in data:
    cnt, grp = i.MinimumNPopulation.split('by')
    cnt = mapped_cols.get(cnt.strip())
    grp = grp.strip()
    sampleData = sampleData.groupBy(f.col(grp)).agg(f.count(f.col(cnt)).alias('count')).\
    filter(f.col('count')>=i.MinimumNValue).drop('count').join(sampleData,grp,'inner')

sampleData.show()
+-------+--------+--------+
|Project|Facility|PeopleID|
+-------+--------+--------+
|     P1|      F1|  166152|
|     P1|      F1|  425906|
|     P1|      F1|  332127|
|     P1|      F1|  241630|
+-------+--------+--------+

注意:您必须手动分析规则语法,因为它可能会发生变化