【问题标题】:alter a dataframe by applying rules from a second dataframe通过应用来自第二个数据帧的规则来更改数据帧
【发布时间】:2018-06-19 15:32:56
【问题描述】:

您好,我有两个数据框。

输入数据框:-

id   number      idsc                 mfd 
738  as6812      *fage abc van brw    amz 
745  786-151     *glaeceau smt sp     amz 
759  b0nadum     ankush 574415 mo...  admz 
764  fdad3-al-c  lib anvest-al...     amz 
887  rec-2s-5    or abc sur...        c 
64   00954       ankush pure g...     amz 
8    0000686     dor must die         a 
3    000adf623   bsc test 10-pi...    amz 

检查条件数据框:-

condition      destinationfield expression                                b_id          
True           idsc             [idsc].lower()                            1 
[mfd]=="amz"   idsc             re.sub(r'\abc\b','a',[idsc])              1 
[mfd]=="admz"  idsc             re.sub(r'and \d+ other item', '', [idsc]) 1 
True           idsc             re.sub(r'[^a-z0-9 ]',r'',[idsc])          1 
True           idsc             [idsc].strip()                            1 
[mfd] == "c"   idsc             re.sub(r'\ankush\b','ank',[idsc])         1 
True           number           re.sub(r'[^0-9]',r'',[number])            1
True           number           [number].strip()                          1 

我正在寻找在输入数据帧上应用条件数据帧的每个规则并获得一个新的数据帧。

如果我的条件为真,那么我需要将它应用于所有行。如果除了 true 之外还有任何特定值,那么我需要将该条件应用于特定记录。

在 pyspark 中是否有更好的方法来执行此操作,因为正则表达式与 python 相关。而不是在 for 循环中运行它。

id   number     idsc              mfd 
738  as6812     *fage a van brw   amz 
745  786-151    *glaeceau smt sp  amz 
759  b0nadum    ank 574415 mo...  admz 
764  fdad3-al-c lib anvest-al...  amz 
887  rec-2s-5   or a sur...       c 
64   00954      ank pure g...     amz 
8    0000686    dor must die      a 
3    000adf623  bsc test 10-pi... amz 

输入数据管道分离

id| number|idsc|mfd 
738|as6812|*fage abc van brw|amz 
745|786-151|*glaeceau smt sp|amz 
759|b0nadum|ankush 574415 mo...|admz 
764|fdad3-al-c|lib anvest-al...|amz 
887|rec-2s-5|or abc sur...|c 
64| 00954|ankush pure g...|amz 
8|0000686|dor must die a 
3|000adf623|bsc test 10-pi...|amz 

条件数据管道分离

条件|目标字段|表达式|b_id|

True|idsc|[idsc].lower()|1 
[mfd]=="amz"|idsc|re.sub(r'\abc\b','a',[idsc])|1 
[mfd]=="admz"|idsc|re.sub(r'and \d+ other item', '', [idsc])|1 
True|idsc|re.sub(r'[^a-z0-9 ]',r'',[idsc])|1 
True|idsc|[idsc].strip()|1 
[mfd] == "c"|idsc|re.sub(r'\ankush\b','ank',[idsc])|1 
True|number|re.sub(r'[^0-9]',r'',[number])|1
True|number|[number].strip()|1 

谢谢, 安库什·雷迪

【问题讨论】:

  • 你能给我们提供我们可以实际复制的数据帧吗?
  • 嗨@user3483203 对我认为我们现在应该能够加载到数据框中的问题进行了更改。谢谢。
  • “条件”数据框是否很大?如果不是,那么要实现这些转换,使用 pyspark.sql.DataFrame 函数将是最有效的。例如 -- df = df.withColumn("idsc", F.lower("idsc")) 将满足您的第一个条件。
  • 我在条件数据框中有大约 14000 条记录。
  • @ankushreddy 14000 条记录似乎不大。是否可以在列表中收集它?

标签: python pyspark


【解决方案1】:

您可以尝试使您的 Condition Dataframe 可评估。

如果它是可评估的,你可以在条件和表达式上调用eval()

def apply_condition(df, df_condition):
 # write a function get_df_evaluable_condition which both does
 # replace "[any_column]" by "df.['any_column']" in createcondition
 # replace "[destinationfield]" by "element" in expression

 df_evaluable_condition = get_df_evaluable_condition(df_evaluable_condition)

 for index, row in df_evaluable_condition.iterrows():
    createcondition = row['createcondition']
    destinationfield = row['destinationfield']
    expression = row['expression']
    # just apply expression where createcondition is true
    df.loc[eval(createcondition), destinationfield] = 
      df.loc[eval(createcondition), destinationfield].apply(lambda element: eval(expression))

顺便说一句,如果表达式包含对不是目标列的列的引用,则最后一行代码将不起作用。你需要更复杂的东西来实现你想要的。

如果您不知道您的 Condition Dataframe 是什么样子,我不建议您使用这种方法。不要在未知字符串上调用eval()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-07-23
    • 1970-01-01
    • 2021-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多