python - 如何匹配两个数据框并得到以下结果?

标签 python pandas numpy dataframe

我有以下 df_project:

df_project = pd.DataFrame({'Project':['A','B','C'],'Day':[1,5,10],'Cost':[100,200,300]})

Project Day Cost
A       1   100
B       5   200
C       10  300

我还有以下 df_ payment:

df_payment = pd.DataFrame({'Payment':['P1','P2','P3','P4','P5','P6'],'Day':[2,3,5,6,7,11],'Amount':[50,40,100,50,70,280]})

Payment Day Amount
P1      2   50
P2      3   40
P3      5   100
P4      6   50
P5      7   70
P6      11  280

我想要得到以下结果:

df_result = pd.DataFrame({'Project':['A','A','A','B','B','B','np.Nan','C','C'],'Payment':['P1','P2',np.nan,'P3','P4','P5','P5','P6',np.nan],'Amount':[50,40,10,100,50,50,20,280,20]})

Project Payment Amount
A       P1      50.0
A       P2      40.0
A       NaN     10.0
B       P3      100.0
B       P4      50.0
B       P5      50.0
NaN     P5      20.0
C       P6      280.0
C       NaN     20.0

逻辑是: 1.付款必须与天数大于或等于的项目匹配

所以我们可以看到P1和P2匹配A,P3,P4,P5匹配B,P6匹配C

  • 付款与项目匹配后 我们基本上有以下数据框:
  • Project Payment 
    A       P1      
    A       P2      
    B       P3      
    B       P4      
    B       P5      
    C       P6      
    

    然后我们还将 df_ payment['Amount'] 与 df_project['Cost'] 进行匹配

    因此 (P1,50) 和 (P2,40) 与 A 匹配,但 A 的成本为 100,赤字为 10,因此付款设置为 NaN

    然后对于项目 B,(P3,100)、(P4,50)、(P5,70) 的盈余为 20,因此该项目设置为 NaN 以获得额外的 20 盈余

    同样,对于项目C(P6,280)有20的赤字,所以结果将是这样的:

    Project Payment Amount
    A       P1      50.0
    A       P2      40.0
    A       NaN     10.0
    B       P3      100.0
    B       P4      50.0
    B       P5      50.0
    NaN     P5      20.0
    C       P6      280.0
    C       NaN     20.0
    

    有什么办法可以做到这一点吗?

    最佳答案

    使用merge_asof在最近的日子合并

    M = pd.merge_asof(df_payment,df_project,on='Day').drop('Day',axis=1)
    

    函数有助于将成本和金额之间的差异附加回数据框

    def attach_difference(df):
        A = df.Amount.sum()
        B = df.Cost.max()
        C = df.shape[0]
        D = df.Payment.iloc[-1]
        df = df.reset_index(drop=True)
        if A-B < 0:
            df.loc[C]=  {'Payment':np.nan,
                         'Amount':abs(A-B), 
                         'Project':df.Project.unique()[0],
                         'Cost':np.nan}
    
        elif A - B > 0 : 
            df.loc[C-1,'Amount'] = df.loc[C-1,'Amount'] - (A-B)
            df.loc[C]=  {'Payment':D,
                         'Amount':A-B, 
                         'Project':np.nan,
                         'Cost':np.nan}
    
    
        return df
    


    运行列表理解并将函数通过管道传输到每个组

    outcome = [group.pipe(attach_difference)
               .drop('Cost',axis=1)
               for name, group in M.groupby('Project')]
    
    (pd.concat(outcome,ignore_index=True)
     .reindex(['Project','Payment','Amount'],
              axis=1)
     )
    
    
    
       Project  Payment Amount
    0     A       P1    50
    1     A       P2    40
    2     A       NaN   10
    3     B       P3    100
    4     B       P4    50
    5     B       P5    50
    6     NaN     P5    20
    7     C       P6    280
    8     C       NaN   20
    

    关于python - 如何匹配两个数据框并得到以下结果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60331269/

    相关文章:

    python - 如何将 Django 命令扩展与新的 Eclipse/Pydev 运行配置一起使用

    python - 这会检测到是否违反了我的最小间距,但不会生成新列表

    python - scrapy 的问题 - 没有抓取任何项目

    python - 如何对一列数据执行行函数并将函数的输出附加到 Pandas data.frame 中?

    python - 翻转已排序数据框的排序顺序

    Python 3.x 无法将 Decimal() 序列化为 JSON

    python - 对数据框列中的值进行自定义过滤器 (Python)

    python - 在 Pandas 数据框中的列子集中查找具有非零值的行

    python - Python 中埃拉托色尼的高效筛法

    python - 使用特定条件创建新列